zoukankan      html  css  js  c++  java
  • POJ 3414 Pots

    http://poj.org/problem?id=3414

    题目描述:

    给你两个容器,分别能装下A升水和B升水,并且可以进行以下操作
    FILL(i)        将第i个容器从水龙头里装满(1 ≤ i ≤ 2);
    DROP(i)        将第i个容器抽干
    POUR(i,j)      将第i个容器里的水倒入第j个容器(这次操作结束后产生两种结果,一是第j个容器倒满并且第i个容器依旧有剩余,二是第i个容器里的水全部倒入j中,第i个容器为空)
    现在要求你写一个程序,来找出能使其中任何一个容器里的水恰好有C升,找出最少操作数并给出操作过程

    Input

    有且只有一行,包含3个数A,B,C(1<=A,B<=100,C<=max(A,B))

    Output

    第一行包含一个数表示最小操作数K
    随后K行每行给出一次具体操作,如果有多种答案符合最小操作数,输出他们中的任意一种操作过程,如果你不能使两个容器中的任意一个满足恰好C升的话,输出“impossible”

    Sample Input

    3 5 4

    Sample Output

    6
    FILL(2)
    POUR(2,1)
    DROP(1)
    POUR(2,1)
    FILL(2)
    POUR(2,1)

    面向题解的思路:
    我们需要找使得某个容器里面的水有C升,并按照题目的操作步骤的话,就是一个一个的尝试。看的大部分题解都是用广搜做的。
    很麻烦的一道题,但总体来看就是一个有六个入口的bfs问题,知道了这个状态的变换,以及结束的条件:尝试遍历无结果以及找到解。根据这些就可以有个大体的轮廓了。
    六个入口分别是:fill (1)
            fill (2)
            drop (1)
            drop (2)
            pour (1)
            pour (2)
    不仅如此,我们变换后状态还要判断在队列中是否已经存在或是有过这种状态。(防止出现多余的枝)
    于是考虑建立一个数组 all 来记录。
    还有就是当前的状态不能影响之前的状态。
    第一个搜索得到的解一定是最优解,或是最优解的其中一个。搜索的深度就代表着达到某个解的最小步数。
    而当我们一层层往下搜索时,大概能够得到一个这样的搜索:


    (哎呀图太大了。。。)

    代码在这,想到再补充,主要思路和学长的题解一样。
     1 #include <bits/stdc++.h>
     2 
     3 #define N 100010
     4 #define maxn 200010
     5 
     6 using namespace std;
     7 
     8 typedef long long int ll;
     9 
    10 int a, b, c;
    11 typedef struct node{
    12     int A;          //某刻A中水量
    13     int B;          //某刻B中水量
    14     int step;       //总数
    15     int temp[N];    //记录步骤
    16 }can;
    17 can x;
    18 int all[110][110]={0};  //记录遍历到的状态
    19 void bfs(){
    20     queue<can> now;
    21     now.push(x);
    22     can y;
    23     while(!now.empty()){
    24         y=now.front();
    25         now.pop();
    26         //A或B容器中有一个满足题意
    27         if(y.A==c || y.B==c){
    28             printf("%d
    ", y.step);
    29             for(int i=0; i<y.step; i++){
    30                 switch(y.temp[i]){
    31                     case 1: printf("FILL(1)
    "); break;
    32                     case 2: printf("FILL(2)
    "); break;
    33                     case 3: printf("DROP(1)
    "); break;
    34                     case 4: printf("DROP(2)
    "); break;
    35                     case 5: printf("POUR(1,2)
    "); break;
    36                     case 6: printf("POUR(2,1)
    "); break;
    37                 }
    38             }
    39             return ;    //可以把这里去掉看全部的解
    40         }
    41         else{
    42             can save;   //替换一下y
    43             //六个入口的bfs
    44             for(int i=1; i<=6; i++){
    45                 save=y;
    46                 save.temp[save.step++]=i; //记录走到当前的总步骤
    47                 switch(i){
    48                     case 1: save.A=a; break;
    49                     case 2: save.B=b; break;
    50                     case 3: save.A=0; break;
    51                     case 4: save.B=0; break;
    52                     case 5:{
    53                         if(save.A+save.B>b) {
    54                             save.A=save.A-(b-save.B);
    55                             save.B=b;
    56                         }
    57                         else{
    58                             save.B=save.A+save.B;
    59                             save.A=0;
    60                         }
    61                     } break;
    62                     case 6:{
    63                         if(save.A+save.B>a){
    64                             save.B=save.B-(a-save.A);
    65                             save.A=a;
    66                         }
    67                         else{
    68                             save.A=save.A+save.B;
    69                             save.B=0;
    70                         }
    71                     } break;
    72                 }
    73                 //检测状态是否重复
    74                 if(all[save.A][save.B]) continue;
    75                 //否则放入队列中
    76                 now.push(save);
    77                 all[save.A][save.B]=1;
    78             }
    79         }
    80     }
    81     printf("impossible
    ");
    82 }
    83 int main()
    84 {
    85     scanf("%d%d%d", &a, &b, &c);
    86     x.A=x.B=0;
    87     x.step=0;
    88     all[0][0]=1;
    89     bfs();
    90     return 0;
    91 }
    
    
    
     
  • 相关阅读:
    通讯录封装实现
    简单通讯录的实现 main..h .m文件全部
    iOS 开发 OC编程 字典和集合 排序方法
    iOS 开发 OC编程 数组冒泡排序.图书管理
    iOS 开发 OC编程 属性和字符串练习
    iOS 开发 OC编程 属性和字符串
    iOS 开发 OC编程 便利构造器以及初始化方法
    iOS 开发 OC编程 方法的书写
    IOS 开发 OC编程 类和对象
    iOS 开发 c语言阶段考试题
  • 原文地址:https://www.cnblogs.com/Arrokoth/p/12194368.html
Copyright © 2011-2022 走看看