POJ 3414 bfs
阿新 • • 發佈:2018-11-26
給你兩個容量為A和B的空水杯,要你通過3種操作(程式中分為了6種)來實現A或B杯中有一個杯子中的水是C升。
三種操作為:
FILL(i):把i杯子裝滿水。
DROP(i):倒空i杯子的水。
POUR(i, j):將i杯子的水倒到j杯子中,只要i杯子為空或j杯子已滿就立即停止。
要求輸出最短操作序列。
分析:
0 倒滿A杯
1 倒滿B杯
2 倒空A杯
3 倒空B杯
4 將A杯倒入B杯
5 將B杯倒入A杯
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<stack> using namespace std; const int maxa=100+5; const int maxb=100+5; const int maxn=110000; int A,B,C; int vis[maxa][maxb],dist[maxa][maxb],pre[maxa][maxb]; struct Cell { int a,b; Cell(int a,int b):a(a),b(b){} }; int cnt;//記錄當前nodes節點總數,從0開始計數到cnt-1 struct Node { int a,b; int t;//操作型別 Node(){} Node(int a,int b,int t):a(a),b(b),t(t){} }nodes[maxn]; queue<Cell> Q; Cell BFS() { cnt=0; memset(vis,0,sizeof(vis)); dist[0][0]=0; vis[0][0]=1; Q.push(Cell(0,0)); while(!Q.empty()) { Cell cell = Q.front();Q.pop(); int a=cell.a,b=cell.b; for(int d=0;d<6;d++) { int na,nb; if(d==0){na=A; nb=b;} else if(d==1){na=a; nb=B;} else if(d==2){na=0; nb=b;} else if(d==3){na=a; nb=0;} else if(d==4) { int all=a+b; na=all>=B?all-B:0; nb=all>=B?B:all; } else if(d==5) { int all=a+b; na=all>=A?A:all; nb=all>=A?all-A:0; } if(vis[na][nb]==0) { vis[na][nb]=1; dist[na][nb]=1+dist[a][b]; nodes[cnt++]=Node(a,b,d); pre[na][nb]=cnt-1; if(na==C||nb==C) { //printf("%d %d %d\n",na,nb,d); return Cell(na,nb);//滿足條件退出 } Q.push(Cell(na,nb)); } } } return Cell(-1,-1); } int main() { scanf("%d%d%d",&A,&B,&C); Cell cell=BFS(); if(cell.a==-1)printf("impossible\n"); else { stack<int> S; //這是棧。 int a=cell.a,b=cell.b; while(a!=0||b!=0) { int p=pre[a][b]; S.push(nodes[p].t); a=nodes[p].a,b=nodes[p].b; } printf("%d\n",S.size()); while(!S.empty()) { int x=S.top();S.pop(); if(x==0||x==1) printf("FILL(%d)\n",x+1); else if(x==2||x==3) printf("DROP(%d)\n",x-1); else if(x==4) printf("POUR(1,2)\n"); else if(x==5)printf("POUR(2,1)\n"); } } return 0; }