POJ 3414 Pots (BFS)

题目链接:http://poj.org/problem?id=3414

题意:

有两个杯子 a 和 b,第一个杯子 a 的最大容量为 A,第二个杯子 b 的最大容量为B,对于这两个杯子有以下三种操作:

  FILL(i):把杯子 i 盛满水.

  DROP(i):把杯子 i 中的水全部倒掉.

  POUR(i, j):把杯子 i 中的水往杯子 j 中倒,直至杯子 j 中的水为满或者杯子 i 中的水为空.

给你这两个杯子的最大容量 A 和 B,问是否能利用以上三种操作使得某时其中一个杯子的水量恰好为 C,如果可以,输出最少的操作次数,以及操作顺序.如果无论如何操作,都不可能使得其中一个杯子的水量为C,那么输出"impossible".

思路:

可以认为两个杯子的初始状态为(0, 0),经过一系列操作要使得其状态变为(*, C)或者(C, *),其中所有的操作一共有六种:

  "FILL(1)":给第一个杯子倒满水;

  "FILL(2)":给第二个杯子到满水;

  "DROP(1)":把第一个杯子的水倒空;

  "DROP(2)":把第二个杯子的水倒空;

  "POUR(1, 2)":把第一个杯子里的水往第二个杯子里倒;

  "POUR(2, 1)":把第二个杯子里的水往第一个杯子里倒.

所以可以采用暴力求解,对于每种状态都有这六种操作,按照这个思路构造出解答树,对这棵树进行BFS,找到到达终止状态的最少操作数,问题就可以解决.

代码:

  1 #include <iostream>
  2 #include <cmath>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <cstdlib>
  6 #include <stack>
  7 #include <queue>
  8 #include <vector>
  9 #include <algorithm>
 10 #include <string>
 11 
 12 typedef long long LL;
 13 typedef unsigned long long ULL;
 14 using namespace std;
 15 const int MAXN = 100;
 16 int MaxA, MaxB, C;//Pots A的最大容量;Pots B的最大容量;目标容量 C;
 17 const string OPERA[] = {"-1", "FILL(1)", "FILL(2)", "DROP(1)", "DROP(2)", "POUR(1,2)", "POUR(2,1)"};//分别代表六种可能的操作
 18 int visit[MAXN + 7][MAXN + 7];//visit[i][j] = 1表示Pots A的水量为 i, Pots B的水量为 j这一状态已经出现过.
 19 
 20 struct Status {
 21     int NowA;//此时A中的水量
 22     int NowB;//此时B中的水量
 23     int step;//到达此状态的操作次数
 24     string order;//到达此状态的所有操作
 25 };
 26 
 27 Status BFS() {
 28     memset(visit, 0, sizeof(visit));
 29     Status fist;//初始状态
 30     fist.NowA = fist.NowB = fist.step = 0;
 31     fist.order = "";
 32     queue<Status> Qu;
 33     Qu.push(fist);//从初始状态开始BFS
 34     visit[0][0] = 1;
 35     while(!Qu.empty()) {
 36         Status temp = Qu.front();
 37         Qu.pop();
 38         if(temp.NowA == C || temp.NowB == C) return temp;//找到目标状态
 39 
 40         Status nex;
 41         
 42         if(temp.NowA != MaxA) {//A中水不为满,可执行操作1 --> FILL(1)
 43             nex.NowA = MaxA, nex.NowB = temp.NowB, nex.step = temp.step + 1;//执行操作1之后,状态发生变化,记录即可
 44             if(nex.step == 1) nex.order = temp.order + OPERA[1];//第一个操作前没有回车......
 45             else nex.order = temp.order + "\n" + OPERA[1];
 46             if(!visit[nex.NowA][nex.NowB]) {//这个状态没有发生过
 47                 Qu.push(nex);
 48                 visit[nex.NowA][nex.NowB] = 1;
 49             }
 50         }
 51 
 52         if(temp.NowB != MaxB) {//B中水不为满,可执行操作2 --> FILL(2)
 53             nex.NowA = temp.NowA, nex.NowB = MaxB, nex.step = temp.step + 1;
 54             if(nex.step == 1) nex.order = temp.order + OPERA[2];
 55             else nex.order = temp.order + "\n" + OPERA[2];
 56             if(!visit[nex.NowA][nex.NowB]) {
 57                 Qu.push(nex);
 58                 visit[nex.NowA][nex.NowB] = 1;
 59             }
 60         }
 61 
 62         if(temp.NowA != 0) {//A中水不为空,可执行操作3 --> DROP(1)
 63             nex.NowA = 0, nex.NowB = temp.NowB, nex.step = temp.step + 1;
 64             if(nex.step == 1) nex.order = temp.order + OPERA[3];
 65             else nex.order = temp.order + "\n" + OPERA[3];
 66             if(!visit[nex.NowA][nex.NowB]) {
 67                 Qu.push(nex);
 68                 visit[nex.NowA][nex.NowB] = 1;
 69             }
 70         }
 71 
 72         if(temp.NowB != 0) {//B中水不为空,可执行操作4 --> DROP(2)
 73             nex.NowA = temp.NowA, nex.NowB = 0, nex.step = temp.step + 1;
 74             if(nex.step == 1) nex.order = temp.order + OPERA[4];
 75             else nex.order = temp.order + "\n" + OPERA[4];
 76             if(!visit[nex.NowA][nex.NowB]) {
 77                 Qu.push(nex);
 78                 visit[nex.NowA][nex.NowB] = 1;
 79             }
 80         }
 81         
 82         if(temp.NowA != 0 && temp.NowB != MaxB) {//A中水不为空,且B中水不为满,可执行操作5 --> POUR(1,2)
 83             nex.NowA = max(0, temp.NowA - (MaxB - temp.NowB)), nex.NowB = min(MaxB, temp.NowA + temp.NowB);
 84             nex.step = temp.step + 1;
 85             if(nex.step == 1) nex.order = temp.order + OPERA[5];
 86             else nex.order = temp.order + "\n" + OPERA[5];
 87             if(!visit[nex.NowA][nex.NowB]) {
 88                 Qu.push(nex);
 89                 visit[nex.NowA][nex.NowB] = 1;
 90             }
 91         }
 92 
 93         if(temp.NowB != 0 && temp.NowA != MaxA) {//B中水不为空,且A中水不为满,可执行操作6 --> POUR(2,1)
 94             nex.NowA = min(MaxA, temp.NowA + temp.NowB), nex.NowB = max(0, temp.NowB - (MaxA - temp.NowA));
 95             nex.step = temp.step + 1;
 96             if(nex.step == 1) nex.order = temp.order + OPERA[6];
 97             else nex.order = temp.order + "\n" + OPERA[6];
 98             if(!visit[nex.NowA][nex.NowB]) {
 99                 Qu.push(nex);
100                 visit[nex.NowA][nex.NowB] = 1;
101             }
102         }
103     }
104     return fist;//没找到答案
105 }
106 
107 int main() {
108     scanf("%d%d%d", &MaxA, &MaxB, &C);
109     Status ans = BFS();
110     if(ans.NowA == C || ans.NowB == C) cout << ans.step << endl << ans.order << endl;
111     else cout << "impossible" << endl;
112     return 0;
113 }

 

posted @ 2016-08-10 08:49  vrsashly  阅读(247)  评论(0编辑  收藏  举报