zoukankan      html  css  js  c++  java
  • HDU1495 非常可乐 (嵌套结构体广搜 对比 一般广搜)

    题意

    大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为。因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要喝的和seeyou一样多。但seeyou的手中只有两个杯子,它们的容量分别是N 毫升和M 毫升 可乐的体积为S (S<101)毫升 (正好装满一瓶) ,它们三个之间可以相互倒可乐 (都是没有刻度的,且 S==N+M,101>S>0,N>0,M>0) 。聪明的ACMER你们说他们能平分吗?如果能请输出倒可乐的最少的次数,如果不能输出"NO"。

    Input

    三个整数 : S 可乐的体积 , N 和 M是两个杯子的容量,以"0 0 0"结束。Output如果能平分的话请输出最少要倒的次数,否则输出"NO"。Sample Input

    7 4 3
    4 1 3
    0 0 0

    Sample Output

    NO
    3
    ---------------------------------------------------------我是分割线----------------------------------------------------------------------------------------------------------------------

    某童靴的一般思路 (感谢@陌类 提供的代码)

      (较麻烦的题解, 好像多数人都这么写~ 

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <algorithm>
      4 #include <queue>
      5 #define N 110
      6 using namespace std;
      7 int vis[N][N][N];
      8 int s,n,m;
      9 struct node
     10 {
     11     int n,s,m,step;
     12 };
     13 int cheak(int x,int y,int z)
     14 {
     15     if(x==0&&y==z)
     16         return 1;
     17     if(y==0&&x==z)
     18         return 1;
     19     if(z==0&&x==y)
     20         return 1;
     21     return 0;
     22 }
     23 int bfs()
     24 {
     25     queue<node>Q;
     26     node now,next;
     27     now.s=s;
     28     now.n=0;
     29     now.m=0;
     30     now.step=0;
     31     vis[s][0][0]=1;
     32     Q.push(now);
     33     while(Q.size())
     34     {
     35         now=Q.front();
     36         Q.pop();
     37         if(cheak(now.s,now.n,now.m))//检查状态
     38         {
     39             return now.step;
     40         }
     41         for(int i=1;i<=6;i++)
     42         {
     43             if(now.s!=0)
     44             {
     45                 if(i==1&&now.n!=n)
     46                 {
     47                     if(now.n+now.s>n)
     48                     {
     49                         next.n=n;
     50                         next.s=now.s-(n-now.n);
     51                     }
     52                     else
     53                     {
     54                         next.n=now.n+now.s;
     55                         next.s=0;
     56                     }
     57                     next.m=now.m;
     58                     next.step=now.step+1;
     59                     if(!vis[next.s][next.n][next.m])
     60                     {
     61                         vis[next.s][next.n][next.m]=1;
     62                         Q.push(next);
     63                     }
     64                 }
     65                 else if(i==2&&now.s!=0&&now.m!=m)
     66                 {
     67                     if(now.m+now.s>m)
     68                     {
     69                         next.m=m;
     70                         next.s=now.s-(m-now.m);
     71                     }
     72                     else
     73                     {
     74                         next.m=now.m+now.s;
     75                         next.s=0;
     76                     }
     77                     next.n=now.n;
     78                     next.step=now.step+1;
     79                     if(!vis[next.s][next.n][next.m])
     80                     {
     81                         vis[next.s][next.n][next.m]=1;
     82                         Q.push(next);
     83                     }
     84                 }
     85             }
     86             if(now.n!=0)
     87             {
     88                 if(i==3&&now.m!=m)
     89                 {
     90                     if(now.m+now.n>m)
     91                     {
     92                         next.m=m;
     93                         next.n=now.n-(m-now.m);
     94                     }
     95                     else
     96                     {
     97                         next.m=now.m+now.n;
     98                         next.n=0;
     99                     }
    100                     next.s=now.s;
    101                     next.step=now.step+1;
    102                     if(!vis[next.s][next.n][next.m])
    103                     {
    104                         vis[next.s][next.n][next.m]=1;
    105                         Q.push(next);
    106                     }
    107                 }
    108                 else if(i==4&&now.n!=0&&now.s!=s)
    109                 {
    110                     if(now.m+now.s>s)
    111                     {
    112                         next.s=s;
    113                         next.n=now.n-(s-now.s);
    114                     }
    115                     else
    116                     {
    117                         next.s=now.n+now.s;
    118                         next.n=0;
    119                     }
    120                     next.m=now.m;
    121                     next.step=now.step+1;
    122                     if(!vis[next.s][next.n][next.m])
    123                     {
    124                         vis[next.s][next.n][next.m]=1;
    125                         Q.push(next);
    126                     }
    127                 }
    128             }
    129             if(now.m!=0)
    130             {
    131                 if(i==5&&now.m!=0&&now.n!=n)
    132                 {
    133                     if(now.n+now.m>n)
    134                     {
    135                         next.n=n;
    136                         next.m=now.m-(n-now.n);
    137                     }
    138                     else
    139                     {
    140                         next.n=now.n+now.m;
    141                         next.m=0;
    142                     }
    143                     next.s=now.s;
    144                     next.step=now.step+1;
    145                     if(!vis[next.s][next.n][next.m])
    146                     {
    147                         vis[next.s][next.n][next.m]=1;
    148                         Q.push(next);
    149                     }
    150                 }
    151                 else if(i==6&&now.m!=0&&now.s!=s)
    152                 {
    153                     if(now.s+now.m>s)
    154                     {
    155                         next.s=s;
    156                         next.m=now.m-(s-now.s);
    157                     }
    158                     else
    159                     {
    160                         next.s=now.s+now.m;
    161                         next.m=0;
    162                     }
    163                     next.n=now.n;
    164                     next.step=now.step+1;
    165                     if(!vis[next.s][next.n][next.m])
    166                     {
    167                         vis[next.s][next.n][next.m]=1;
    168                         Q.push(next);
    169                     }
    170                 }
    171 
    172             }
    173         }
    174     }
    175     return -1;
    176 }
    177 int main()
    178 {
    179     while(scanf("%d%d%d",&s,&n,&m),s+n+m!=0)
    180     {
    181         if(s%2!=0)
    182         {
    183             printf("NO\n");
    184         }
    185         else
    186         {
    187             memset(vis,0,sizeof(vis));
    188             int ans;
    189             ans=bfs();
    190             if(ans>=0)
    191             printf("%d\n",ans);
    192             else
    193                 printf("NO\n");
    194         }
    195     }
    196     return 0;
    197 }
    View Code 

     简单点评

      在上面的代码, 每次for循环都将枚举六种情况 ,1->2 , 1-》3,2-》3 ,2-》1,3-》1,3-》2  ,并且每种情况又要分为两种来讨论......

       重复的部分太多了~

      重复的部分太多了~ 

      不够简洁,代码太长长了。

      出错误了一不好找啊!

    -------------------------------------------------------------------------------------------------------------------------------------我是分割线---------------------------------------------------------------------------------------------------------------------------------------------------------------------------

      起先我也是这么做的,后来我想了一个相对简单的优化办法:

      进行结构体的嵌套 ,结构体cup 的 a[1]/a[2]/a[3]分别代表这 三个容器 ,其中结构体 cup中 up 代表一个容器的装水上限 ,now  代表现在的水量! 再用 结构体node 将cup和step 封装起来!

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstdio>
     4 #include<cstring>     //by  @山枫叶纷飞
     5 #include<cstdlib>
     6 #include<cmath>
     7 #include<string>
     8 #include<set>
     9 #include<queue>
    10 using namespace std;
    11 typedef long long ll;
    12 double dinf=99999999.9, mm=1e-8;
    13 const int N=108,inf=0x3f3f3f3f;
    14 int s,n,m;
    15 int vis[N][N][N];
    16 struct cup
    17 {
    18     int up,now;
    19 };
    20 struct node
    21 {
    22      cup a[4];  ///进行结构体的嵌套 ,a[1]/a[2]/a[3] 分别表示三个容器
    23     int step;
    24 };
    25 int bfs( )
    26 {
    27     int i,j,k;
    28     queue<node>Q;
    29     node p,q;
    30     p.a[1].now=s;p.a[1].up=s;
    31     p.a[2].now=0;p.a[2].up=n;
    32     p.a[3].now=0;p.a[3].up=m;
    33     p.step=0;
    34     memset(vis,0,sizeof(vis));vis[s][0][0]=1;
    35     Q.push(p);
    36     while(Q.size()>0)
    37     {
    38         p=Q.front(); ///从队列中取到的现在的状态
    39         Q.pop();
    40         if((p.a[1].now==s/2&&p.a[2].now==s/2) || (p.a[1].now==s/2&&p.a[3].now==s/2))///判断是否达到预期结果
    41             return p.step;
    42         if((p.a[2].now==s/2&&p.a[3].now==s/2))///判断是否达到预期结果(太长了,拆成了两段)
    43             return p.step;
    44             
    45         for(i=1;i<=3;i++)
    46         {
    47             for(j=1;j<=3;j++)
    48             {
    49                 if(i==j || p.a[i].now==0||p.a[j].now==p.a[j].up)///简易排除
    50                     continue;
    51                     
    52                 q=p;///初始化,q 代表由p 延伸来的下一状态
    53                 
    54                int dif=p.a[j].up-p.a[j].now;///表示容器a[j]最多可添加水量
    55                 if(p.a[i].now>=dif)///若容器a[j]可被填满水
    56                 {
    57                     q.a[i].now=p.a[i].now-dif;
    58                     q.a[j].now=p.a[j].up;
    59                 }
    60                 else ///若容器a[j]不能装满水
    61                 {
    62                     q.a[i].now=0;
    63                     q.a[j].now=p.a[i].now+p.a[j].now;
    64                 }
    65                 q.step=p.step+1;
    66                 if(vis[q.a[1].now][q.a[2].now][q.a[3].now]==0)
    67                 {
    68                     vis[q.a[1].now][q.a[2].now][q.a[3].now]=1;
    69                     Q.push(q);
    70                 }
    71             }
    72         }
    73 
    74 
    75     }
    76     return -1;
    77 }
    78 int main()
    79 {
    80     while(scanf("%d%d%d",&s,&n,&m),s+n+m)
    81     {
    82         if(s%2!=0)///奇数一定无法均分成两份
    83             printf("NO\n");
    84         else
    85         {
    86             int k=bfs();
    87             if(k==-1)
    88                 printf("NO\n");
    89             else
    90                 printf("%d\n",k);
    91         }
    92     }
    93 
    94     return 0;
    95 }
    View Code

     简单点评

      两重for 循环,用a[i] 和a[j] 来模拟全部六种情况的倒水过程 ,省了超过100行的代码, 结构体的含义一目了然,  就是结构体名字写起来太长了!

      还有要注意的是: { q=p;///初始化,q 代表由p 延伸来的下一状态}这段代码的位置很重要, 每次新的内层for循环都要记得将q重新初始化, 不然会造成意料之外的错误! 当时debug 到了 "debug人在天涯"!


    ---------------------------------------------------------我是分割线----------------------------------------------------------------------------------------------------------------------
    其他思路
      这个题目用数论也是可以做的! 近似玄学,,,感兴趣的话自行百度!
    你不逼自己一把,你永远都不知道自己有多优秀!只有经历了一些事,你才会懂得好好珍惜眼前的时光!
  • 相关阅读:
    Golang相关环境变量
    mac catalina关闭系统更新提示
    Git常用命令
    UDP打洞原理
    LANMP相关配置
    Windows平台编译libevent
    Sublime text2 + cygwin编译C++
    C++的指针常量和常量指针
    C++的new和delete
    C/C++产生随机数
  • 原文地址:https://www.cnblogs.com/zhazhaacmer/p/7290705.html
Copyright © 2011-2022 走看看