倒水问题(water)
有两个无刻度标志的水杯,分别可装x升和y升的水。设另一个水缸,可以用来向水杯灌水或从水杯向水缸里倒水,两个水杯之间也可以相互倒水。已知x升的水杯开始是盛满水的,y升的杯子是空的,问如何通过倒水和灌水操作,用最少的步数能在y升的杯子里量出z升水。
输入:
一行:x,y,z(<=100),整数。中间一个空格隔开。
输出:
第一行:最少步数s。
以下共s行,每行两个用空格隔开的整数,第一个表示操作一次后,x杯中的水的数量,第二个整数表示y杯中的水的数量。
样例:
输入:
20 15 10
输出:
5
step0:20 0(注意step0这一行不输出)
step1:5 15
step2:0 15
step3:15 0
step4:15 15
step5:20 10
#include
#include
using namespace std;
intf[110][110],b[110][110],head,tail,step,i,j,p[10010],q[10010],a[10010];
void dfs(int l)
{
if(a[l]==0)
{
return;
}
dfs(a[l]);
cout<<"step"<<b[p[l]][q[l]]<<":";
cout<<p[l]<<""<<q[l]<<endl;
step++;
return;
}
int main()
{
freopen("water.in","r",stdin);
freopen("water.out","w",stdout);
intx,y,z;
cin>>x>>y>>z;
f[x][0]=1;
b[x][0]=0;
tail++;
p[tail]=x;
q[tail]=0;
a[tail]=0;
while(head
{
i=p[head+1];
j=q[head+1];
if(i-(y-j)>=0&&f[i-(y-j)][y]==0)//将X倒入Y,使y满
{
f[i-(y-j)][y]=1;
tail++;
p[tail]=i-(y-j);
q[tail]=y;
a[tail]=head+1;
b[i-(y-j)][y]=b[i][j]+1;
}
if(i-(y-j)<0)//将X全部倒入Y,Y不满
if(f[0][i+j]==0&&i!=0)
{
f[0][i+j]=1;
tail++;
p[tail]=0;
q[tail]=i+j;
a[tail]=head+1;
b[0][i+j]=b[i][j]+1;
}
if(j-(x-i)>=0&&f[x][j-(x-i)]==0)//将Y倒入X,使X满
{
f[x][j-(x-i)]=1;
tail++;
p[tail]=x;
q[tail]=j-(x-i);
a[tail]=head+1;
b[x][j-(x-i)]=b[i][j]+1;
}
if (j-(x-i)<0)//将y全部倒入X,X不满
if(f[j+i][0]==0&&j!=0)
{
f[j+i][0]=1;
tail++;
p[tail]=j+i;
q[tail]=0;
a[tail]=head+1;
b[j+i][0]=b[i][j]+1;
}
if(f[0][j]==0&&j!=0)//将X全部倒入缸,且保证X,Y不同时空,否则还需重新倒水
{
f[0][j]=1;
tail++;
p[tail]=0;
q[tail]=j;
a[tail]=head+1;
b[0][j]=b[i][j]+1;
}
if (f[i][0]==0&&i!=0)//将Y全部倒入缸
{
f[i][0]=1;
tail++;
p[tail]=i;
q[tail]=0;
a[tail]=head+1;
b[i][0]=b[i][j]+1;
}
if (f[x][j]==0)//将X用缸中的水灌满
{
f[x][j]=1;
tail++;
p[tail]=x;
q[tail]=j;
a[tail]=head+1;
b[x][j]=b[i][j]+1;
}
if (f[i][y]==0) //将Y用缸中的水灌满
{
f[i][y]=1;
tail++;
p[tail]=i;
q[tail]=y;
a[tail]=head+1;
b[i][y]=b[i][j]+1;
}
if(q[tail]==z)
break;
head++;
}
cout<<b[p[tail]][q[tail]]<<endl;
dfs(tail);
return0;
}
用水杯中水的状态进行广搜