看到用最少次数就会想到要用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; }个人愚昧观点...欢迎指正与讨论