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 }
    
    
    
     
  • 相关阅读:
    CF 120F Spider 树的直径 简单题
    POJ 1155 TELE 背包型树形DP 经典题
    CF 219D Choosing Capital for Treeland 树形DP 好题
    POJ 3162 Walking Race 树形DP+线段树
    HDU 2196 Computer 树形DP 经典题
    __str__()、__repr__()和__format__()
    item系列方法
    getattribute
    isinstance和issubclass
    继承方式完成包装
  • 原文地址:https://www.cnblogs.com/Arrokoth/p/12194368.html
Copyright © 2011-2022 走看看