nyoj 21-三个水杯(BFS)
21-三个水杯
内存限制:64MB
时间限制:1000ms
Special Judge: No
accepted:7
submit:18
题目描述:
给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子。三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算。现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数。
输入描述:
第一行一个整数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
分析:
①、题目要求的是最少的倒水次数,即就是最短步数问题;
②、对上一步产生的结果下一步应该怎样应对,用队列来考虑每一步的结果;
③、用BFS的思想模拟,每一次(从6种倒水可能中进行抉择与判断)倒水将会参会什么样的结果
步骤:
①、初始化队列的首相,即就是最开始的水的分配情况
②、循环6步操作,考虑同样的水在6中不同情况下的分配如何,分别入队列
③、依次遍历出所有的情况,如果可以得到结果的话,就输出步骤,否则如果遍历完了都没能得到结果就return -1
核心代码:
1 int bfs() 2 { 3 queue<node> Q; 4 node q1, q2; 5 memset(book, 0, sizeof(book)); 6 q1.temp[0] = A[0], q1.temp[1] = 0, q1.temp[2] = 0; 7 book[q1.temp[0]][0][0] = 1; 8 Q.push(q1); 9 while(!Q.empty()) 10 { 11 q1 = Q.front(); 12 if(q1.temp[0] == B[0] && q1.temp[1] == B[1] 13 && q1.temp[2] == B[2]) 14 return q1.step; 15 for(int i = 0; i < 3; ++ i) 16 { 17 for(int j = 0; j < 3; ++ j) 18 { 19 if (i == j) continue; // 自己不向自己倒水 20 q2 = q1; 21 int my_change = min(q1.temp[i], A[j] - q1.temp[j]); // 将i杯中的水倒入j杯,A[j] - q1.temp[j],表明j杯最多可以得到的水量 22 q2.temp[i] = q1.temp[i] - my_change; 23 q2.temp[j] = q1.temp[j] + my_change; 24 q2.step = q1.step + 1; 25 if(!book[q2.temp[0]][q2.temp[1]][q2.temp[2]]) 26 { 27 book[q2.temp[0]][q2.temp[1]][q2.temp[2]]; 28 Q.push(q2); 29 } 30 } 31 } 32 Q.pop(); 33 } 34 return -1; 35 }
C/C++代码实现(AC):
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <cstdio> 5 #include <cmath> 6 #include <stack> 7 #include <map> 8 #include <queue> 9 10 using namespace std; 11 const int MAXN = 110; 12 int A[5], B[5], book[MAXN][MAXN][MAXN]; 13 struct node 14 { 15 int temp[3], step; 16 }; 17 18 bool match(node q, int a, int b, int c) 19 { 20 if(q.temp[0] == a && q.temp[1] == b && q.temp[2] == c) return true; 21 return false; 22 } 23 24 int bfs() 25 { 26 node q1, q2; 27 q1.temp[0] = A[0], q1.temp[1] = 0, q1.temp[2] = 0, q1.step = 0; 28 queue<node> Q; 29 Q.push(q1); 30 memset(book, 0, sizeof(book)); 31 book[A[0]][0][0] = 1; 32 while(!Q.empty()) 33 { 34 q1 = Q.front(); 35 if(match(q1, B[0], B[1], B[2])) return q1.step; 36 for(int i = 0; i < 3; ++ i) // 倒水的方式有6种 37 { 38 for(int j = 0; j < 3; ++ j) 39 { 40 if(i == j) continue; 41 int my_op = min(q1.temp[i], A[j] - q1.temp[j]); // 将i杯子里面的水倒到j杯子中 42 q2 = q1; 43 q2.temp[i] = q1.temp[i] - my_op; 44 q2.temp[j] = q1.temp[j] + my_op; 45 q2.step ++; 46 if(!book[q2.temp[0]][q2.temp[1]][q2.temp[2]]) 47 { 48 book[q2.temp[0]][q2.temp[1]][q2.temp[2]] = 1; 49 Q.push(q2); 50 } 51 } 52 } 53 Q.pop(); 54 } 55 return -1; 56 } 57 58 int main() 59 { 60 int t; 61 scanf("%d", &t); 62 while(t --) 63 { 64 memset(book, 0, sizeof(book)); 65 scanf("%d%d%d", &A[0], &A[1], &A[2]); 66 scanf("%d%d%d", &B[0], &B[1], &B[2]); 67 printf("%d\n", bfs()); 68 } 69 return 0; 70 }