看到用最少次数就会想到要用bfs,那么主要就是搜索过程中的处理:对于三个杯子我们标记为0,1,2...我们总共有以下6种情况的倒水情况:
、、、
、那么,对于杯子先有的一种状态,对于每一种状态,我们用一个结构体来保存,里面包括当前三个杯子的水量,最开始的状况到现在状况倒水的次数step,那么在此状态下,我们就对六种情况判断,能不能这样倒水,能就入队列,能倒水的判断我们要不出现以前倒水过程中出现过得状态,不超过水杯容量、、、、、等
下面是我的详细代码注释(对于此题,还可以用dfs,每次达到要求状态就更新一下步数让其最小)
// 时间12 内存1436
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
int six[6][2]={{0,1},{0,2},{1,0},{1,2},{2,0},{2,1}};//六种倒水的方法
bool flag[105][105][105];//看是否出现过
struct cup//杯子的状态
{
int a[3];
int step;
}CUP,start,end;//这里的start和end就是用来存放开始输入的杯子,和最终状态的
int del(cup &cc,int x,int y)//将cc的状态改变,从x倒水到y中
{
if(cc.a[x]!=0 || cc.a[y]!=start.a[y])//不出现这两情况:没水可倒,或者b水杯现在有的水就是我们最开始输入的水杯大小,意思就是满了...
{
if(cc.a[x]+cc.a[y]<=start.a[y])//吧x中全部倒入y中都不大于y杯子的大小
{
cc.a[y]+=cc.a[x];
cc.a[x]=0;//x倒完
}
else
{
cc.a[x]-=(start.a[y]-cc.a[y]);//首先这种情况是不能把y倒满,那么x就会倒掉(start.a[y]-cc.a[y]),这个差就是y由现在到满所需的水
cc.a[y]=start.a[y];//y倒满,注意一定不要和上面的式子弄反,否则y先改变,x的剩余也会不正确
}
if(!flag[cc.a[0]][cc.a[1]][cc.a[2]])//这种状态没有到过
{
flag[cc.a[0]][cc.a[1]][cc.a[2]]=true;
return 1;
}
}
return 0;
}
int bfs()
{
cup CUP;//
CUP.a[0]=start.a[0];
CUP.a[1]=CUP.a[2]=CUP.step=0;//初始化状态,注意别CUP=start,因为我们这个状态是只有最大的杯子是满的,其他为0
queue<cup>q;
q.push(CUP);
flag[CUP.a[0]][CUP.a[0]][CUP.a[2]]=true;
while(!q.empty())
{
cup pre=q.front();
q.pop();
if(pre.a[0]==end.a[0] && pre.a[1]==end.a[1] && pre.a[2]==end.a[2])
return pre.step;
for(int i=0;i<6;i++)
{
cup p=pre;//用一个临时变量
if(del(p,six[i][0],six[i][1]))//处理看能否倒水,能就操作,并且保留操作后的状态,入队
{
p.step=pre.step+1;
//printf("%d %d %d %d\n",p.a[0],p.a[1],p.a[2],p.step);
q.push(p);
}
}
}
return -1;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(flag,false,sizeof(flag));
scanf("%d%d%d",&start.a[0],&start.a[1],&start.a[2]);
scanf("%d%d%d",&end.a[0],&end.a[1],&end.a[2]);
printf("%d\n",bfs());
}
return 0;
}
dfs 改正的在下面
#include<stdio.h>
#include<string.h>
struct cup
{
int a[4];
int step;
}start,end;
bool flag[105][105][105];
int ans;
int vis[6][2]={{1,2},{1,3},{2,1},{2,3},{3,1},{3,2}};
bool del(cup & c,int x,int y)
{
if(c.a[x]==0 || c.a[y]==start.a[y])
return false;
if(c.a[x]+c.a[y]>start.a[y])
{
c.a[x]-=(start.a[y]-c.a[y]);
c.a[y]=start.a[y];
}
else
{
c.a[y]+=c.a[x];
c.a[x]=0;
}
if(flag[c.a[1]][c.a[2]][c.a[3]])
return false;
return true;
}
void dfs(cup CUP)
{
if(CUP.a[1]==end.a[1] && CUP.a[2]==end.a[2] && CUP.a[3]==end.a[3])
{
if(CUP.step<ans)//这里搜索到就与ans(也就是我们的答案比较一下..取小的)
ans=CUP.step;
return;
}
for(int i=0;i<6;i++)
{
cup c;c.a[1]=CUP.a[1];c.a[2]=CUP.a[2];c.a[3]=CUP.a[3];
if(del(c,vis[i][0],vis[i][1]))
{
flag[c.a[1]][c.a[2]][c.a[3]]=true;
c.step=CUP.step+1;
dfs(c);
flag[c.a[1]][c.a[2]][c.a[3]]=false;
}
}
return ;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
ans=10000;
memset(flag,false,sizeof(flag));
scanf("%d%d%d",&start.a[1],&start.a[2],&start.a[3]);
scanf("%d%d%d",&end.a[1],&end.a[2],&end.a[3]);
flag[start.a[1]][0][0]=true;
cup p;p.a[1]=start.a[1];p.a[2]=p.a[3]=p.step=0;
dfs(p);
if(ans<100)
printf("%d\n",ans);
else
printf("-1\n");
}
return 0;
}
个人愚昧观点...欢迎指正与讨论