首页 > 代码库 > HDU-1495 非常可乐 (嵌套结构体-广搜 对比 一般广搜)

HDU-1495 非常可乐 (嵌套结构体-广搜 对比 一般广搜)

题意

大家一定觉的运动以后喝可乐是一件很惬意的事情,但是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人在天涯"!


---------------------------------------------------------我是分割线----------------------------------------------------------------------------------------------------------------------
其他思路
  这个题目用数论也是可以做的! 近似玄学 , 最近正在整理中!敬请期待!

HDU-1495 非常可乐 (嵌套结构体-广搜 对比 一般广搜)