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 }

 


posted @ 2018-05-20 23:01  GetcharZp  阅读(818)  评论(0编辑  收藏  举报