题目大意:给出两个空杯子,已知这两个空杯子的容量,有无限多的水,再给出要求得到的体积,找出一种方法,得到要求的体积
解决:BFS+路径记录
#include <iostream> #include <cstdio> #include <queue> using namespace std; int ca,cb,n,ex,ey; //有六种选择方案,记录的时候只需要记录下,方案的代号0-6即可 char p[6][20]={"fill A","fill B","pour B A","pour A B","empty A","empty B"}; //bfs离不开判断是否走过,否则会陷入死循环 bool vis[1000][1000]; struct node { int x,y; node(){} node(int xx,int yy):x(xx),y(yy){} }; struct pos { int x,y; int kind; pos(){} pos(int xx,int yy,int k):x(xx),y(yy),kind(k){} }; //存储路径的数组,路径中存放该结点是从哪个结点扩展而来的 pos path[1000][1000]; void bfs() { queue<node> q; q.push(node(0,0)); vis[0][0]=1; node now; path[0][0]=pos(-1,-1,0); while(!q.empty()) { now=q.front(); if(now.x==n ||now.y==n)return; q.pop(); if(!vis[ca][now.y]) {//fill A的情况,不一定A为空才能fill A vis[ca][now.y]=1; q.push(node(ca,now.y)); path[ca][now.y]=pos(now.x,now.y,0); if(ca==n){ ex=ca; ey=0; return; } } if(!vis[now.x][cb]) { vis[now.x][cb]=1; q.push(node(now.x,cb)); path[now.x][cb]=pos(now.x,now.y,1); if(cb==n){ ex=0; ey=cb; return; } } if(now.x!=ca && now.y!=0 ) {//pour B A的情况,这要分两种状态,一种是将A倒满,一种是将B倒空 if(now.x+now.y >= ca && !vis[ca][now.x+now.y-ca]) { vis[ca][now.x+now.y-ca]=1; q.push(node(ca,now.x+now.y-ca)); path[ca][now.x+now.y-ca]=pos(now.x,now.y,2); if(now.x+now.y-ca==n){ ex=ca; ey=now.x+now.y-ca; return;} } else if(now.x + now.y < ca && !vis[now.x+now.y][0]) { vis[now.x+now.y][0]=1; q.push(node(now.x+now.y,0)); path[now.x+now.y][0]=pos(now.x,now.y,2); if(now.x+now.y==n){ ex=now.x+now.y; ey=0; return;} } } if(now.y!=cb && now.x!=0) {//pour A B的情况,一种是将B倒满,一种是将A倒空 if(now.x+now.y >= cb && !vis[now.x+now.y-cb][cb]) { vis[now.x+now.y-cb][cb]=1; q.push(node(now.x+now.y-cb,cb)); path[now.x+now.y-cb][cb]=pos(now.x,now.y,3); if(now.x+now.y-cb==n){ ex=now.x+now.y-cb; ey=cb; return;} } else if(now.x + now.y < cb && !vis[0][now.x+now.y]) { vis[0][now.x+now.y]=1; q.push(node(0,now.x+now.y)); path[0][now.x+now.y]=pos(now.x,now.y,3); if(now.x+now.y==n){ now.x=0; now.y=now.x+now.y; return;} } } if(!vis[0][now.y]) {//empty A的情况,不一定A满了才能倒空 vis[0][now.y]=1; q.push(node(0,now.y)); path[0][now.y]=pos(now.x,now.y,4); } if(!vis[now.x][0]) {//empty B的情况,不一定B满了才能倒空 vis[now.x][0]=1; q.push(node(now.x,0)); path[now.x][0]=pos(now.x,now.y,5); } } } void print(int x,int y) { if(path[x][y].x!=-1 && path[x][y].y!=-1) { print(path[x][y].x,path[x][y].y); printf("%s\n",p[path[x][y].kind]); } } int main() { while(cin>>ca>>cb>>n) { memset(vis,0,sizeof(vis)); bfs(); print(ex,ey); cout<<"success"<<endl; } system("pause"); return 0; }
poj 3414和此题一模一样,但是下边代码,提供一种不同的记录路径的方式,用string来记录,从起始到当前扩展结点的所有路
经,而不是仅仅记录该结点是由哪个结点扩展来的。
#include <iostream> #include <cstdio> #include <queue> #include <cstring> #include <string> using namespace std; int ca,cb,n,ex,ey; char p[6][20]={"FILL(1)","FILL(2)","POUR(2,1)","POUR(1,2)","DROP(1)","DROP(2)"}; bool vis[105][105]; struct node { int x,y; int step; //string 方法记录路径 string way; node(){} node(int xx,int yy,int s,string w):x(xx),y(yy),step(s),way(w){} }; string res; /* struct pos { int x,y; int kind; pos(){} pos(int xx,int yy,int k):x(xx),y(yy),kind(k){} }; pos path[105][105]; */ int bfs() { queue<node> q; q.push(node(0,0,0,"")); vis[0][0]=1; node now; while(!q.empty()) { now=q.front(); if(now.x==n ||now.y==n){res=now.way; return now.step;} q.pop(); if(!vis[ca][now.y]) { vis[ca][now.y]=1; q.push(node(ca,now.y,now.step+1,now.way+"0")); if(ca==n){ res=q.back().way; return now.step+1; } } if(!vis[now.x][cb]) { vis[now.x][cb]=1; q.push(node(now.x,cb,now.step+1,now.way+"1")); if(cb==n){ res=q.back().way; return now.step+1; } } if(now.x!=ca && now.y!=0 ) { if(now.x+now.y >= ca && !vis[ca][now.x+now.y-ca]) { vis[ca][now.x+now.y-ca]=1; q.push(node(ca,now.x+now.y-ca,now.step+1,now.way+"2")); if(now.x+now.y-ca==n){ res=q.back().way; return now.step+1; } } else if(now.x + now.y < ca && !vis[now.x+now.y][0]) { vis[now.x+now.y][0]=1; q.push(node(now.x+now.y,0,now.step+1,now.way+"2")); if(now.x+now.y==n){ res=q.back().way; return now.step+1; } } } if(now.y!=cb && now.x!=0) { if(now.x+now.y >= cb && !vis[now.x+now.y-cb][cb]) { vis[now.x+now.y-cb][cb]=1; q.push(node(now.x+now.y-cb,cb,now.step+1,now.way+"3")); if(now.x+now.y-cb==n){ res=q.back().way; return now.step+1; } } else if(now.x + now.y < cb && !vis[0][now.x+now.y]) { vis[0][now.x+now.y]=1; q.push(node(0,now.x+now.y,now.step+1,now.way+"3")); if(now.x+now.y==n){ res=q.back().way; return now.step+1; } } } if(!vis[0][now.y]) { vis[0][now.y]=1; q.push(node(0,now.y,now.step+1,now.way+"4")); } if(!vis[now.x][0]) { vis[now.x][0]=1; q.push(node(now.x,0,now.step+1,now.way+"5")); } } return -1; } int main() { cin>>ca>>cb>>n; memset(vis,0,sizeof(vis)); int t=bfs(); if(t >=0 ) { cout<<t<<endl; int n=res.size(); for(int i=0;i<n;i++) puts(p[res[i]-'0']); } else cout<<"impossible"<<endl; system("pause"); return 0; }