(不易)POJ-3414 BFS中的路径还原
来源:互联网 发布:李炎恢javascript笔记 编辑:程序博客网 时间:2024/05/21 00:47
题目大意:
给出了两个瓶子的容量A,B, 以及一个目标水量C,
对A、B可以有如下操作:
FILL(i) 装满i瓶
DROP(i) 清空i瓶
POUR(i,j) 把i瓶都倒入j瓶中,若j已满则超出的部分的仍留在i中
问经过哪几个操作后能使得任意一个瓶子的残余水量为C。
题目链接:点击打开链接
分析:这题很明显用BFS,BFS其实也就一个模版并没有难点,所以最少操作次数很容易求出,这里的难点在于按顺序输出所有的操作,这个问题在最短路问题中也是独立出来的一个问题—路径还原。我们可以把每一个操作都当成是一个走法,于是对操作的输出便转化称了路径的还原。如果还没有接触个这个问题的童鞋们可以先看看我这篇文章:点击打开链接
相信大家在看完路径还原的方法与技巧之后,对这题应该也是有一点思路了。不错,这个题我们会用到文章最后的2个常见问题的解决技巧。我用0-5来分别代表BFS的5个入口(或者说方向),并且在记录路径的同时记录下这些不同入口。我会在代码注释中更加详细地进行解释的,请看完代码。
附上代码:
#include<iostream> //POJ-3414#include<queue>#include<algorithm>using namespace std;int d[105][105];bool vis[105][105];int a, b, c;int A, B;struct st //x,y分别代表1,2容器中当前的水量{int x, y;st(int a = 0, int b = 0){ x = a, y = b; }};struct Prv //用来记录路径(注意这里并不是真正意义上的路!),prv[x1][y1].last_x=x2,prv[x1][y1].last_y=y2{ //代表了(x1,y1)的前驱节点为(x2,y2),prv[x1][y1].kase=i则代表(x2,y2)是经由动作i到达的(x1,y1)int last_x, last_y;int kase;}prv[105][105];queue<st> q;st solve(st &v, int kase){int x = v.x, y = v.y;if (kase == 0) x = a;else if (kase == 1) y = b;else if (kase == 2) x = 0;else if (kase == 3) y = 0;else if (kase == 4){int ty = y;y = min(b, x + y);x = x + ty - y;}else{int tx = x;x = min(a, x + y);y = y + tx - x;}return st(x, y);}int bfs(){q.push(st(0, 0));vis[0][0] = 1;prv[0][0].kase = -1;while (!q.empty()){st v = q.front();q.pop();for (int i = 0; i<6; i++) //0-5分别代表FILL(1),FILL(2),DROP(1),DROP(2),POUR(1,2),POUR(2,1)这6种操作(动作){st t = solve(v, i); //求出执行操作i之后的状态(即1,2容器中的当前水量)int fx = t.x, fy = t.y;if (!vis[fx][fy]){vis[fx][fy] = 1;d[fx][fy] = d[v.x][v.y] + 1;q.push(st(fx, fy));Prv &tt = prv[fx][fy]; //记录下路径,注意一定别忘了&!!!tt.last_x = v.x;tt.last_y = v.y;tt.kase = i;if (fx == c || fy == c) //注意出口放在!vis[fx][fy]里,所以若一开始的(0,0)就满足条件那么结果肯定不对{//但这题C!=0,所以可以放心,否则需在主函数中判断一下A = fx, B = fy;return d[fx][fy];}}}}return -1;}int main(){scanf("%d%d%d", &a, &b, &c);int ans = bfs(); if (!~ans) printf("impossible\n");else{printf("%d\n", ans);Prv t = prv[A][B];vector<st> path; //将路径放入path中path.push_back(st(A, B));for (; t.kase != -1; t = prv[t.last_x][t.last_y])path.push_back(st(t.last_x, t.last_y));reverse(path.begin(), path.end()); //由于路径是从目的地到起点,所以要反转for (int i = 1; i < path.size(); i++) //输出路径,由于起始状态到其下一个状态的操作记录在后一个状态的prv里,所以i从1开始{int t = prv[path[i].x][path[i].y].kase;if (t == 0) printf("FILL(1)");else if (t == 1) printf("FILL(2)");else if (t == 2) printf("DROP(1)");else if (t == 3) printf("DROP(2)");else if (t == 4) printf("POUR(1,2)");else printf("POUR(2,1)");printf("\n");}}return 0;}
0 0
- (不易)POJ-3414 BFS中的路径还原
- poj 3984 bfs+路径还原
- POJ 3414 Pots ( BFS , 打印路径 )
- POJ 3414--Pots(BFS+回溯路径)
- poj 3414 Pots (bfs+路径记录)
- POJ 3414 Pots(BFS记录路径)
- POJ -3414 Pots(BFS + 打印路径)
- poj 3414 Pots (BFS + 记录路径)
- POJ 3414 Pots(bfs+路径记录)
- POJ-3414 POTS(BFS打印路径)
- POJ 3414 bfs求路径(建bfs树然后树上寻找路径)
- POJ 3414 Pots(bfs + 判重 + 输出路径)
- poj 3414 Pots(广搜BFS+路径输出)
- poj 3414 Pots(bfs+string(储存路径))
- POJ 3414 Pots【BFS+记录路径】
- POJ 3414 Pots (BFS + 记录路径)
- POJ 3414 Pots (BFS+路径打印)
- poj-3414-Pots【BFS+记录路径】
- CSUST 第九届校赛C-编辑距离(DP)
- 求关于一条直线的对称点
- 图解密码技术笔记(一)对称密码(共享密钥密码)——用相同的密钥进行加密和解密
- Android5.X对图形操作上有更多的功能。下面来看看Tinting(着色)
- 使用hibernate进行CRUD
- (不易)POJ-3414 BFS中的路径还原
- Unity实现滑页嵌套(解决ScrollRect嵌套冲突问题)
- 一个专注于细分行业的网址导航-6指南针网址导航
- Nginx简单介绍以及安装与配置
- Python学习笔记(六)
- 初来乍到
- HDU 1358 Period
- CSS块级元素、内联元素概念
- 笔试题--动态规划