HDU 1495 非常可乐(BFS)

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

 

题意:
三个杯子已知容量,只有一杯可乐,来回倒,问多少次能把可乐均分成两份
题意很简单的,关键是思路

 

思路:
倒的过程只有六种,即6个方向,要求的操作数类似于其他bfs要求的步数
把题中的s n m用数组存,来回倒的过程就能用里外两个循环写,方便一点

 

代码:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 
 5 int b[5];
 6 struct node
 7 {
 8     int a[5];
 9     int step;
10 } str[1005], x, y;
11 int vis[105][105][105];
12 
13 void bfs(int s)
14 {
15     if(s%2!=0) printf("NO\n");
16     else if(b[1]==s/2) printf("1\n");
17     else
18     {
19         int i, j, in, out;
20         in = 0;
21         out = 0;
22         x.a[0] = s;
23         x.a[1] = 0;
24         x.a[2] = 0;
25         x.step = 0;
26         str[in++] = x;
27         while(in>out)
28         {
29             x = str[out++];  //得到最末尾的一个状态
30             for(i=0; i<3; i++)    //x.a[i]往外倒
31             {
32                 if(x.a[i]==0) continue;  //有的倒
33                 for(j=0; j<3; j++)    //x.a[j]往里接
34                 {
35                     if(i==j) continue;    //不能一个杯子操作!(一开始这里也没写,样例能过,但是代码不对)
36                     y = x;
37                     if(x.a[i]+x.a[j] >= b[j])  //能倒满
38                     {                          //注意里面式子都是不能倒过来的
39                         y.a[i] = x.a[i] + x.a[j] - b[j];
40                         y.a[j] = b[j];
41                     }
42                     else  //不能倒满
43                     {
44                         y.a[j] = x.a[i] + x.a[j];
45                         y.a[i] = 0;
46                     }
47                     if(vis[y.a[0]][y.a[1]][y.a[2]]==0)   //如果这个状态是新的,判断+进队列
48                     {
49                         y.step++;
50                         if((y.a[0]==b[0]/2&&y.a[1]==b[0]/2)  //一开始把判断写在判断上面的x了,
51                                   //每次判断最后一个,超时了。应该是得到一个状态就判断
52                                   //避免后知后觉做了一些无谓的动作
53                                 ||(y.a[0]==b[0]/2&&y.a[2]==b[0]/2)
54                                 ||(y.a[1]==b[0]/2&&y.a[2]==b[0]/2)
55                           )
56                         {
57                             printf("%d\n", y.step);
58                             return;
59                         }
60                         str[in++] = y;
61                         vis[y.a[0]][y.a[1]][y.a[2]] = 1;
62                     }
63                 }
64             }
65         }
66         printf("NO\n");
67     }
68 }
69 
70 int main()
71 {
72     while(~scanf("%d %d %d", &b[0], &b[1], &b[2]))
73     {
74         if(!b[0]&&!b[1]&&!b[2]) break;
75         memset(vis, 0, sizeof(vis));
76         vis[b[0]][0][0] = 1;
77         bfs(b[0]);
78     }
79     return 0;
80 }

 

转载于:https://www.cnblogs.com/0xiaoyu/p/11356310.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值