POJ 3414 得到想要的容量 BFS
来源:互联网 发布:nodejs json增加字段 编辑:程序博客网 时间:2024/06/06 09:22
题目在: http://poj.org/problem?id=3414
题目的大意是: 给你两个容量固定的烧杯,容量分别是A和B,如何得到体积是C的水,只有如下操作是合法的
1. 装满A,从水源处获得
2. 装满B
3, 将A倒给B,倒完后或者B倒满了,或者A空了
4. 将B倒给A,倒完后或者A满了,或者B空了
5. 将A清空
6. 将B清空
求出最少的步骤可以使得从最初两个空杯,得到体积为C水,其中容量为C的水,可以放在任何一个容器中。
Sample Input
3 5 4
Sample Output
6FILL(2)POUR(2,1)DROP(1)POUR(2,1)FILL(2)POUR(2,1)
分析:此题的分类是BFS,不过自己想半天也没有想清楚如何BFS,看了discussion里的一些提示,才所有顿悟。
在BFS的过程中,当前的状态是两个数,ca,cb,描述当前a烧杯中有水ca,b烧杯中有水cb。
因为下一步只有六种选择的情况,所以我们把这六个情况都枚举出来,例如当权枚举到stepi,如果经过这一步的操作,达到的状态出现过,我们就不将新状态放入队列,
否则作为新的状态放入队列。
我们要记录路径,所以还要保留每个状态之前的状态,同时也有保存到达当前状态的时候,经历了多少步。
所以每个状态里面的有如下值:
1. 两个烧杯的容量 2. 前一个状态 3.到当前状态步骤 4 到这个状态所采用的操作。
代码如下:
#include <stdio.h>#include <memory.h>#define MAX_NUM 101#define MAX_Q MAX_NUM * MAX_NUMenum OPERATION{FILL1 = 0, FILL2, POUR12, POUR21, DROP1, DROP2, NONE};struct Step{int liter1;int liter2;int stepID;OPERATION operation;int previous;Step(){}Step(int l1, int l2, int step, OPERATION op, int previous){liter1 = l1;liter2 = l2;stepID = step;operation = op;this->previous = previous;}};struct Queue{Step steps[MAX_Q];int front;int rear;void ini(){memset(steps, 0, sizeof(steps));front = rear = 0;}void push(int l1, int l2, int step, int privous, OPERATION op){steps[rear++] = Step(l1, l2, step, op, privous);}};bool visit[MAX_NUM][MAX_NUM];Queue q;void PrintPath(int i){if( i == -1){return ;}PrintPath(q.steps[i].previous);switch(q.steps[i].operation){case FILL1:printf("FILL(1)\n");break;case FILL2:printf("FILL(2)\n");break;case POUR12:printf("POUR(1,2)\n");break;case POUR21:printf("POUR(2,1)\n");break;case DROP1:printf("DROP(1)\n");break;case DROP2:printf("DROP(2)\n");break;}}void BFS(int a, int b, int c){q.ini();q.push(0, 0, 0, -1, NONE);visit[0][0] = true;Step nxt,current;while(q.rear > q.front){current = q.steps[q.front++];if(current.liter1 == c || current.liter2 == c){break;}OPERATION iOp;for( int i = 0; i < 6; i++){iOp = (OPERATION)i;nxt = current;switch(iOp){case FILL1:{//fill glass aif( !visit[a][nxt.liter2] ){q.push(a, nxt.liter2, current.stepID + 1, q.front - 1, FILL1);visit[a][nxt.liter2] = true;}break;}case FILL2:{if( !visit[nxt.liter1][b] ){q.push(nxt.liter1, b, current.stepID + 1, q.front - 1, FILL2);visit[nxt.liter1][b] = true;}break;}case POUR12:{int newA = current.liter1;int newB = current.liter2;if(newA + newB > b){newA = newA + newB - b;newB = b;}else{newB = newA + newB;newA = 0;}if(!visit[newA][newB]){q.push(newA, newB, current.stepID + 1, q.front - 1, POUR12);visit[newA][newB] = true;}break;}case POUR21:{int newA = current.liter1;int newB = current.liter2;if(newA + newB > a){newB = newA + newB - a;newA = a;}else{newA = newA + newB;newB = 0;}if(!visit[newA][newB]){q.push(newA, newB, current.stepID + 1, q.front - 1, POUR21);visit[newA][newB] = true;}break;}case DROP1:{if( !visit[0][nxt.liter2] ){q.push(0, nxt.liter2, current.stepID + 1, q.front - 1, DROP1);visit[0][nxt.liter2] = true;}break;}case DROP2:{if( !visit[nxt.liter1][0] ){q.push(nxt.liter1, 0, current.stepID + 1, q.front - 1, DROP2);visit[nxt.liter1][0] = true;}break;}}}}if( q.front == q.rear){printf("impossible\n");}else{printf("%d\n", q.steps[q.front-1].stepID);PrintPath(q.front-1);}}int main(){int a,b,c;while(scanf("%d%d%d", &a, &b, &c) != EOF){memset(visit, 0, sizeof(visit));BFS(a, b, c);}return 0;}
编写的时候犯了好几个bug,导致半天都调不通
bug1, 在newA newB赋值的时候,将顺序写错,忽略了两个值存在依赖关系的事实。
bug2, 最后遍历的时候,没有写front-1, 其实front在上次取完了的时候,就已经-1.
- POJ 3414 得到想要的容量 BFS
- POJ 3414 Pots(容量BFS)
- 使用datetimetostring得到想要的日期格式
- 什么才是自己想要得到的?
- 我是这样得到想要的薪水
- 我是这样得到想要的薪水
- js date 得到自己想要的格式
- 怎样做才能得到自己想要的
- 如何得到你想要的东西
- 成功是得到你想要的,幸福是想要的东西正好得到
- 想要 与 得到
- 得到与想要
- 只要想要,注定得到
- 想要得到更多的团队具有的七个习惯
- 如何得到一个自己想要大小的窗口
- Springboot中随时获取ApplicationContext,得到想要的bean
- POJ 3414 Pots BFS
- poj 3414 搜索BFS
- DBID,SID,DB_NAME,DB_DOMAIN,INSTANCE_NAME,DB_UNIQUE_NAME,SERVICE_NAMES 及监听参数的说明
- Android中关联源码
- 几个常用的小接口
- ios扫描公共区域内的全部wifi信息
- Android的style属性讲解(1)
- POJ 3414 得到想要的容量 BFS
- 使用MongoDB开发实践体会
- Windows Store apps开发[7]视图模型与数据绑定
- javascript正则表达式函数详解
- 文件和文件夹的操作
- Oraclae备份与恢复:exp和imp命令
- 对ffmpeg中的sws_scale的封装类
- css样式兼容不同浏览器问题
- {{JS}}可变长度的参数列表: Arguments对象