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 }

 

 简单点评

  在上面的代码, 每次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 }

 简单点评

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

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

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

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

C语言 结构体(嵌套结构体--结构体数组)

//结构体--嵌套结构体和结构体数组 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct _parent{ int num; char name[30]; //结构体内部定义结构体,如果不定义嵌套结构体变量,那么该嵌套结构体的属性则会被当作父结构体的属性 struct son{ int age; char sna

BFS(倒水问题) HDU 1495 非常可乐

题目传送门 1 /* 2 BFS:倒水问题,当C是奇数时无解.一共有六种情况,只要条件符合就入队,我在当该状态vised时写了continue 3 结果找了半天才发现bug,泪流满面....(网上找份好看的题解都难啊) 4 */ 5 /************************************************ 6 Author :Running_Time 7 Created Time :2015-8-4 10:54:16 8 File Name :HDOJ_1495.cpp

HDU 1495 非常可乐 (BFS)

 问题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1495 题目大意:一个瓶子容积s,两个杯子容积分别n,m,并且都没有刻度(不能比对噢!).相互倒水,求平分的他们的最少倒水次数. 思路:暴力搜索吧.并且求最少,(即最优解),所以上BFS: 思考:状态,转移过程,怎么剪纸. 惨痛的debug,我不解释了. 源代码: #include<iostream> #include<cstdio> #include<queue> #

结构体嵌套结构体名

转自:http://atu82.bokee.com/6706799.html 前一段时间在看DDK中例子的时候,看到这样的的结构体定义: typedef struct _COMMON_DEVICE_DATA { PDEVICE_OBJECT Self; BOOLEAN IsFDO; ...... } COMMON_DEVICE_DATA, *PCOMMON_DEVICE_DATA; typedef struct _PDO_DEVICE_DATA { COMMON_DEVICE_DATA; //

HDU 1495——非常可乐( BFS )

非常可乐 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4663    Accepted Submission(s): 1868 Problem Description 大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为.因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要

HDU 1495 非常可乐(数论,BFS)

非常可乐 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 14153    Accepted Submission(s): 5653 Problem Description 大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为.因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定

hdu 1495 非常可乐【广度优先搜索】

非常可乐 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5109    Accepted Submission(s): 2060 Problem Description 大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为.因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要

HDU 1495 非常可乐 BFS

题目大意:中文题不说了. 题目思路:我有同学用GCD数论写出来的代码很简洁,但是很抱歉,数论蒟蒻,我觉得比赛的时候我没办法推出.如果用BFS的话思路很简单的,就是6方向广搜,只不过稍微麻烦点.具体看代码吧. #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<iostream> #define M

HDU 1495 非常可乐(BFS倒水问题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1495 题目大意:只有两个杯子,它们的容量分别是N 毫升和M 毫升 可乐的体积为S (S<101)毫升 (正好装满一瓶) ,它们三个之间可以相互倒可乐 (都是没有刻度的,且 S==N+M,101>S>0,N>0,M>0) .如果能将可乐平分则输出倒可乐的最少的次数,如果不能输出"NO". 解题思路:题意很坑看了半天,就是要有两个杯子里的可乐都为S/2,S为奇数肯