题目链接:http://poj.org/problem?id=3414
解题报告:
1、每个节点都是一个独立的状态
2、这里的状态转移就是有几种出路,4种:1、倒掉a中的水,2、把a中的水倒到b中去,3、倒掉b 中的水,4、把b中的水倒到a中去
3、每次的步骤记录到str[][]中去
4、搜索最短路径
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; struct Node { int a; ///a杯子里面的水 int b; ///b杯子里面的水 int step; ///到a,b的情况下所用的步数 char str[105][105]; ///str[i]存有解时,step=i时的操作 }; int A,B,C; ///A,B表示两个杯子的容量,C目标容量 bool mark[105][105]; ///mark[i][j]表示在两个杯子在i,j的情况是否标记 bool bfs() { memset(mark,false,sizeof(mark)); queue<Node>que; Node p,tmp; p.a=0,p.b=0,p.step=0; que.push(p); mark[0][0]=true; while(!que.empty()) { p=que.front(); que.pop(); ///搜索到解 if(p.a==C||p.b==C) { printf("%d ",p.step); for(int i=1; i<=p.step; i++) printf("%s ",p.str[i]); return true; } if(p.a==0) { tmp=p; tmp.a=A;///倒满 tmp.step++; strcpy(tmp.str[tmp.step],"FILL(1)"); if(!mark[tmp.a][tmp.b]) { mark[tmp.a][tmp.b]=true; que.push(tmp); } } else if(p.a<=A) ///可以选择倒掉,也可以选择倒到2杯子中去 { tmp=p; tmp.a=0;///倒掉 tmp.step++; strcpy(tmp.str[tmp.step],"DROP(1)"); if(!mark[tmp.a][tmp.b]) { mark[tmp.a][tmp.b]=true; que.push(tmp); } if(p.b<B) { tmp=p; if(tmp.a+tmp.b<=B) { tmp.b+=tmp.a; tmp.a=0; } else { tmp.a=(tmp.b+tmp.a)-B; tmp.b=B; } tmp.step++; strcpy(tmp.str[tmp.step],"POUR(1,2)"); if(!mark[tmp.a][tmp.b]) { mark[tmp.a][tmp.b]=true; que.push(tmp); } } } if(p.b==0) { tmp=p; tmp.b=B;///倒满 tmp.step++; strcpy(tmp.str[tmp.step],"FILL(2)"); if(!mark[tmp.a][tmp.b]) { mark[tmp.a][tmp.b]=true; que.push(tmp); } } else if(p.b<=B) ///可以选择倒掉,也可以选择倒到1中 { tmp=p; tmp.b=0; ///倒掉 tmp.step++; strcpy(tmp.str[tmp.step],"DROP(2)"); if(!mark[tmp.a][tmp.b]) { mark[tmp.a][tmp.b]=true; que.push(tmp); } if(p.a<A) ///倒到1中 { tmp=p; if(tmp.b+tmp.a<=A) { tmp.a+=tmp.b; tmp.b=0; } else { tmp.b=(tmp.b+tmp.a)-A; tmp.a=A; } tmp.step++; strcpy(tmp.str[tmp.step],"POUR(2,1)"); if(!mark[tmp.a][tmp.b]) { mark[tmp.a][tmp.b]=true; que.push(tmp); } } } } return false; } int main() { while(scanf("%d%d%d",&A,&B,&C)!=EOF) { if(!bfs()) puts("impossible"); } return 0; }