描述
给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子。三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算。现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数。
输入
第一行一个整数N(0<N<50)表示N组测试数据 接下来每组测试数据有两行,第一行给出三个整数V1 V2 V3 (V1>V2>V3 V1<100 V3>0)表示三个水杯的体积。 第二行给出三个整数E1 E2 E3 (体积小于等于相应水杯体积)表示我们需要的最终状态
输出
每行输出相应测试数据最少的倒水次数。如果达不到目标状态输出-1
样例输入
2 6 3 1 4 1 1 9 3 2 7 1 1
样例输出
3 -1
题目链接:
http://acm.nyist.net/JudgeOnline/problem.php?pid=21
思路分析:
总共三个杯子,所以在一次选择的时候,共有6种方案,此处设杯子的标号为1, 2, 3, 分为为:1->2, 2->1, 1->3, 3->1, 2->3, 3->2这六种方案可供选择,而每种方案又出现 了被倒的杯子会不会被倒满这两种情况。因为本着简单处理,所以写了6个大选择,每个大选择 里面又会出现两种小选择。将每次倒水之后的三个杯子的状态进行标记,有效地进行剪枝,最后 用BFS实现迭代,然后找到符合条件的情况时,输出当前时间,即为最小的次数,所以还有创建 结构体用来存放三个杯子的水量和当前的时间。大体思路就是如此,不懂可以相互讨论,方法比 较好懂,是给看者提供思路而已。
具体代码:
#include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <queue> using namespace std; struct Status{ int first; int second; int third; int time; }bg,ed; int v1, v2, v3; bool vis[105][105][105]; void BFS(Status s){ queue<Status> que; que.push(s); memset(vis, false, sizeof(vis)); vis[bg.first][0][0] = true; while(que.empty() == false){ Status s1 = que.front(), s2; que.pop(); if(s1.first == ed.first && s1.second == ed.second && s1.third == ed.third){ printf("%d ", s1.time); return; } if(s1.first != 0 && s1.second != v2){// 1 -> 2 if(s1.first + s1.second > v2){//倒不尽 s2.first = s1.first - (v2 - s1.second); s2.second = v2; }else{//倒得尽 s2.first = 0; s2.second = s1.first + s1.second; } s2.third = s1.third; if(vis[s2.first][s2.second][s2.third] == false){ s2.time = s1.time + 1; que.push(s2); vis[s2.first][s2.second][s2.third] = true; } } if(s1.second != 0 && s1.first != v1){// 2 -> 1 if(s1.first + s1.second > v1){//倒不尽 s2.second = s1.second - (v1 - s1.first); s2.first = v1; }else{//倒得尽 s2.second = 0; s2.first = s1.first + s1.second; } s2.third = s1.third; if(vis[s2.first][s2.second][s2.third] == false){ s2.time = s1.time + 1; que.push(s2); vis[s2.first][s2.second][s2.third] = true; } } if(s1.first != 0 && s1.third != v3){// 1 -> 3 if(s1.first + s1.third > v3){//倒不尽 s2.first = s1.first - (v3 - s1.third); s2.third = v3; }else{//倒得尽 s2.first = 0; s2.third = s1.first + s1.third; } s2.second = s1.second; if(vis[s2.first][s2.second][s2.third] == false){ s2.time = s1.time + 1; que.push(s2); vis[s2.first][s2.second][s2.third] = true; } } if(s1.third != 0 && s1.first != v1){// 3 -> 1 if(s1.first + s1.third > v1){//倒不尽 s2.third = s1.third - (v1 - s1.first); s2.first = v1; }else{//倒得尽 s2.third = 0; s2.first = s1.first + s1.third; } s2.second = s1.second; if(vis[s2.first][s2.second][s2.third] == false){ s2.time = s1.time + 1; que.push(s2); vis[s2.first][s2.second][s2.third] = true; } } if(s1.second != 0 && s1.third != v3){// 2 -> 3 if(s1.second + s1.third > v3){//倒不尽 s2.second = s1.second - (v3 - s1.third); s2.third = v3; }else{//倒得尽 s2.second = 0; s2.third = s1.second + s1.third; } s2.first = s1.first; if(vis[s2.first][s2.second][s2.third] == false){ s2.time = s1.time + 1; que.push(s2); vis[s2.first][s2.second][s2.third] = true; } } if(s1.third != 0 && s1.second != v2){// 3 -> 2 if(s1.second + s1.third > v2){//倒不尽 s2.third = s1.third - (v2 - s1.second); s2.second = v2; }else{//倒得尽 s2.third = 0; s2.second = s1.second + s1.third; } s2.first = s1.first; if(vis[s2.first][s2.second][s2.third] == false){ s2.time = s1.time + 1; que.push(s2); vis[s2.first][s2.second][s2.third] = true; } } } puts("-1"); } int main(){ int T; scanf("%d", &T); while(T--){ scanf("%d%d%d", &v1, &v2, &v3); scanf("%d%d%d", &ed.first, &ed.second, &ed.third); if(v1 != ed.first + ed.second + ed.third){ puts("-1"); continue; } bg.first = v1; bg.second = bg.third = bg.time = 0; BFS(bg); } return 0; }
简化代码之后:
#include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <queue> using namespace std; struct Status{ int water[3]; int time; }bg,ed; int v[3]; bool vis[105][105][105]; int dir[6][3] = {{0, 1, 2}, {1, 0, 2}, {0, 2, 1}, {2, 0, 1}, {1, 2, 0}, {2, 1, 0}}; int d[6] = {1, 0, 2, 0, 2, 1}; void BFS(Status s){ queue<Status> que; que.push(s); memset(vis, false, sizeof(vis)); vis[bg.water[0]][0][0] = true; while(que.empty() == false){ Status s1 = que.front(), s2; que.pop(); if(s1.water[0] == ed.water[0] && s1.water[1] == ed.water[1] && s1.water[2] == ed.water[2]){ printf("%d ", s1.time); return; } for(int i=0; i<6; i++){ if(s1.water[dir[i][0]] != 0 && s1.water[dir[i][1]] != v[d[i]]){// 1 -> 2 if(s1.water[dir[i][0]] + s1.water[dir[i][1]] > v[d[i]]){//倒不尽 s2.water[dir[i][0]] = s1.water[dir[i][0]] - (v[d[i]] - s1.water[dir[i][1]]); s2.water[dir[i][1]] = v[d[i]]; }else{//倒得尽 s2.water[dir[i][0]] = 0; s2.water[dir[i][1]] = s1.water[dir[i][0]] + s1.water[dir[i][1]]; } s2.water[dir[i][2]] = s1.water[dir[i][2]]; if(vis[s2.water[0]][s2.water[1]][s2.water[2]] == false){ s2.time = s1.time + 1; que.push(s2); vis[s2.water[0]][s2.water[1]][s2.water[2]] = true; } } } } puts("-1"); } int main(){ int T; scanf("%d", &T); while(T--){ for(int i=0; i<3; i++) scanf("%d", &v[i]); scanf("%d%d%d", &ed.water[0], &ed.water[1], &ed.water[2]); if(v[0] != ed.water[0] + ed.water[1] + ed.water[2]){ puts("-1"); continue; } bg.water[0] = v[0]; bg.water[1] = bg.water[2] = bg.time = 0; BFS(bg); } return 0; }