poj 3414 倒水问题 bfs
2015-04-29 20:34
274 查看
链接:http://poj.org/problem?id=3414
思路:就是bfs,有六种操作,FILL 1或2,DROP 1或2 ,将1倒到2,将2倒到1。要注意的是要使用标记数组vis[i][j] 表示左边的杯子为i升,右边的杯子为j升,如果已被标记说明之前已经出现这种情况,就不要入队。从(0,0)开始bfs。
因为题目中需要输出如何倒,那么就需要保存路径。。以前似乎自己还没有写过,只是知道这种思想,用一个数组记录下当前位置的前一个位置的坐标。最后通过终点找回去,找出整条路径,将路上的每个点都保存到答案数组中,(这里我是逆着保存的,也就是终点保存在最后面),最后输出的时候顺着遍历一遍答案数组,比较前后两个的情况,输出操作。
代码:
思路:就是bfs,有六种操作,FILL 1或2,DROP 1或2 ,将1倒到2,将2倒到1。要注意的是要使用标记数组vis[i][j] 表示左边的杯子为i升,右边的杯子为j升,如果已被标记说明之前已经出现这种情况,就不要入队。从(0,0)开始bfs。
因为题目中需要输出如何倒,那么就需要保存路径。。以前似乎自己还没有写过,只是知道这种思想,用一个数组记录下当前位置的前一个位置的坐标。最后通过终点找回去,找出整条路径,将路上的每个点都保存到答案数组中,(这里我是逆着保存的,也就是终点保存在最后面),最后输出的时候顺着遍历一遍答案数组,比较前后两个的情况,输出操作。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <stack> using namespace std; #define M 109 #define INF 0x3f3f3f3f int vis[M][M]; int n,m,k; int ans; struct state { int x,y; int step; }cur,next1; struct { int lx,ly; }s[M][M]; //记录路径 保存上一个点坐标 struct { int a,b; }ss[100009]; //保存答案的数组 void bfs(state temp) { queue<state> q; temp.step = 0; s[temp.x][temp.y].lx = 0; s[temp.x][temp.y].ly = 0; vis[temp.x][temp.y] = 0; q.push(temp); while(!q.empty()) { cur = q.front(); vis[cur.x][cur.y] = 1; q.pop(); if(cur.x==k || cur.y==k) { ans = cur.step; printf("%d\n",ans); int i = ans; ss[i].a = cur.x; ss[i--].b = cur.y; int xx = s[cur.x][cur.y].lx; int yy = s[cur.x][cur.y].ly; while(i!=-1) { ss[i].a = xx; //从后往前保存答案。 ss[i--].b = yy; int temp1 = xx; int temp2 = yy; xx = s[temp1][temp2].lx; yy = s[temp1][temp2].ly; } return ; } next1.step = cur.step+1; if(cur.y < m) //倒满y { next1.x = cur.x; next1.y = m; if(!vis[next1.x][next1.y]) { //要有括号。。。不然没有加入队列也保存了路径。。。 q.push(next1); s[next1.x][next1.y].lx = cur.x; //只有加入队列才保存路径 s[next1.x][next1.y].ly = cur.y; } } if(cur.x < n) //倒满x { next1.x = n; next1.y = cur.y; if(!vis[next1.x][next1.y]) { q.push(next1); s[next1.x][next1.y].lx = cur.x; s[next1.x][next1.y].ly = cur.y; } } if(cur.x > 0) { next1.x = 0; //倒空x next1.y = cur.y; if(!vis[next1.x][next1.y]) { q.push(next1); s[next1.x][next1.y].lx = cur.x; s[next1.x][next1.y].ly = cur.y; } if(cur.y < m) //x倒到y { if(cur.x > m-cur.y) { next1.x = cur.x-(m-cur.y); next1.y = m; } else { next1.x = 0; next1.y = cur.y+cur.x; } if(!vis[next1.x][next1.y]) { q.push(next1); s[next1.x][next1.y].lx = cur.x; s[next1.x][next1.y].ly = cur.y; } } } if(cur.y > 0) { next1.x = cur.x; //倒空y next1.y = 0; if(!vis[next1.x][next1.y]) { q.push(next1); s[next1.x][next1.y].lx = cur.x; s[next1.x][next1.y].ly = cur.y; } if(cur.x < n)//y倒到x { if(cur.y > n-cur.x) { next1.x = n; next1.y = cur.y-(n-cur.x); } else { next1.x = cur.x+cur.y; next1.y = 0; } if(!vis[next1.x][next1.y]) { q.push(next1); s[next1.x][next1.y].lx = cur.x; s[next1.x][next1.y].ly = cur.y; } } } } } int main() { while(scanf("%d %d %d",&n,&m,&k)==3) { memset(vis,0,sizeof(vis)); memset(ss,0,sizeof(ss)); memset(s,0,sizeof(s)); ans = INF; cur.x = 0; cur.y = 0; bfs(cur); if(ans==INF) printf("impossible\n"); else { //ss[0].a = 0; //ss[0].b = 0; for(int i = 0;i < ans;i++) { int x1 = ss[i].a; int y1 = ss[i].b; int x2 = ss[i+1].a; int y2 = ss[i+1].b; if(x1==0 && x2==n && y1==y2) printf("FILL(1)\n"); //要写清楚情况 fill的时候必须y是不变的。。 if(y1==0 && y2==m && x1==x2) printf("FILL(2)\n"); if(x1>0 && x2==0 && y1==y2) printf("DROP(1)\n"); if(x2>0 && y2==0 && x1==x2) printf("DROP(2)\n"); if(y2>y1 && x2<x1) printf("POUR(1,2)\n"); if(x2>x1 && y2<y1) printf("POUR(2,1)\n"); } } } return 0; }
相关文章推荐
- POJ 3414 Pots【bfs模拟倒水问题】
- poj 3414 pots (bfs 倒水问题)
- POJ3414 Pots【倒水问题+BFS】
- POJ 3414 Pots(BFS倒水问题)
- POJ 3414 Pots【bfs模拟倒水问题】
- poj 3414 Pots [bfs - 倒水问题]
- POJ 3414 Pots【bfs模拟倒水问题】
- poj 3414 Pots [bfs - 倒水问题]
- POJ 3414 - Easy BFS - 六入口倒水问题
- POJ 3414-Pots(BFS-模拟倒水)
- poj 3414 bfs 两个壶倒水,记录路径
- POJ 3414 Pots(BFS 倒水)
- poj3414 倒水问题
- 倒水问题学习小记 Poj 1606 + 3414 + Hdu 1495 + UVA 10603
- POJ 3414 dfs倒水问题
- POJ-3414-两个杯子倒水问题(宽搜+回溯)
- poj3414 倒水问题
- POJ-3414(Pots)——BFS
- POJ 3414 Pots(BFS)
- POJ1077、HDU1043 Eight 八数码问题:双向BFS、A*