• 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 + "
    " + 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 + "
    " + 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 + "
    " + 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 + "
    " + 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 + "
    " + 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 + "
    " + 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 }
  • 相关阅读:
    linux查找杀死进程
    设计模式
    解决导出excel数字为科学计数法问题
    K8S 容器运行时安全设置
    记一次dirty_ratio引起的线上事故
    配置rabbitmq
    k8s集群数据的备份和恢复
    ZK集群安装简易步骤
    Zookeeper 集群环境搭建
    Xcode
  • 原文地址:https://www.cnblogs.com/Ash-ly/p/5755327.html
Copyright © 2020-2023  润新知