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一起分享这一瓶可乐,而且一定要喝的和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
Author
seeyou
Source
“2006校园文化活动月”之“校庆杯”大学生程序设计竞赛暨杭州电子科技大学第四届大学生程序设计竞赛
Recommend
LL
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1495
分析:设两个小瓶子容积分别为a,b,问题转化成通过两个小瓶子的若干次倒进或倒出操作得到(a+b)/2体积的可乐,设两个小瓶子被倒进或倒出x次和y次(这里的x和y是累加后的操作,即x=第一个瓶子倒出的次数-倒进的次数,y=第二个瓶子倒出的次数-倒进的次数),那么问题转化成:
所以|x+|y|的最小值为(c+d)/2,通过x和y的通解形式显然可以看出x和y一正一负,不妨设x<0,那么就是往第一个小瓶子倒进x次,第二个小瓶子倒出y次,但是由于瓶子容积有限,所以倒进倒出操作都是通过大瓶子来解决的,一次倒进操作后为了继续使用小瓶子还要将小瓶子中可乐倒回大瓶子中,倒出操作同理,所以总操作次数是(c+d)/2*2=c+d,但是注意最后剩下的(a+b)/2体积的可乐一定是放在两个小瓶子中较大的那个中,而不是再倒回到大瓶子中,所以操作数要减一,答案就是c+d-1 下面给出AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3 int gcd(int a,int b)
4 {
5 return b==0?a:gcd(b,a%b);
6 }
7 int main()
8 {
9 int a,b,c;
10 while(cin>>a>>b>>c&&(a&&b&&c))
11 {
12 a/=gcd(b,c);
13 if(a&1)
14 cout<<"NO"<<endl;
15 else
16 cout<<a-1<<endl;
17 }
18 return 0;
19 }
给出BFS解法吧 分析:
这题代码有150行 但是基本是六中情况的重复了
先说题目 给三个数字 s n m s=n+m s在1到100之间
就是个倒水问题可以从第一个倒向第二个 类似的一共可以有六中到发
现在要求最少经过多少步就能平分那么多水
首先剪枝是 如果s是奇数必然不行。
一看到要求最少的步数就知道用bfs了
我们用vis标记状态
每个状态有三个整数组成 表示这三个杯子里的可乐数量
然后对每个状态的递推是 6种 也就是3!种。从一个到到另一个 再标记 入队
所以 题目还是蛮简单的
下面给出AC代码:
1 #include<cstdio>
2 #include<cstring>
3 #include<queue>
4 using namespace std;
5 int v[5];
6 int sign[110][110][100];
7 struct cup//记录遍历中3个水杯容藏可乐情况
8 {
9 int v[5];
10 int step;
11 }temp;
12
13 void pour(int a,int b)//倒水函数,把a杯子中的可乐倒到b杯子中
14 {
15 int sum=temp.v[a]+temp.v[b];
16 if(sum>=v[b])
17 temp.v[b]=v[b];
18 else
19 temp.v[b]=sum;
20 temp.v[a]=sum-temp.v[b];
21 }
22
23 void bfs()
24 {
25 int i,j;
26 queue<cup>q;
27 cup cnt;
28 cnt.v[1]=v[1];
29 cnt.v[2]=0;
30 cnt.v[3]=0;
31 cnt.step=0;
32 q.push(cnt);
33 memset(sign,0,sizeof(sign));
34 sign[v[1]][0][0]=1;
35 while(!q.empty())
36 {
37 cnt=q.front();
38 q.pop();
39 if(cnt.v[1]==cnt.v[3]&&cnt.v[2]==0)
40 {
41 printf("%dn",cnt.step);
42 return ;
43 }
44 for(i=1;i<4;++i)
45 {
46 for(j=1;j<4;++j)
47 {
48 if(i!=j)//自己不倒水给自己
49 {
50 temp=cnt;//每个水位情况都要把所有操作枚举一遍,所以都要赋值为原始水位情况
51 pour(i,j);
52 if(!sign[temp.v[1]][temp.v[2]][temp.v[3]])
53 {
54 temp.step++;
55 q.push(temp);
56 sign[temp.v[1]][temp.v[2]][temp.v[3]]=1;
57 }
58 }
59 }
60 }
61 }
62 printf("NOn");
63 }
64
65 int main()
66 {
67 while(scanf("%d%d%d",&v[1],&v[2],&v[3])&&v[1]||v[2]||v[3])
68 {
69 if(v[2]>v[3])
70 {
71 int t=v[2];
72 v[2]=v[3];
73 v[3]=t;
74 }
75 bfs();
76 }
77 return 0;
78 }
- 网站访问状态和超时时间监控报警设置
- 为treeview添加客户端事件
- Flash/Flex学习笔记(20):贝塞尔曲线
- 磁盘挂载问题:Fdisk最大只能创建2T分区的盘,超过2T使用parted
- asp.net中几种页面元素的比较
- Flash/Flex学习笔记(19):颜色合成与分解的基本原理
- Flash/Flex学习笔记(18):画线及三角函数的基本使用
- Mapx自带的工具的理解
- 水晶报表的推模式
- Flash/Flex学习笔记(17):按键捕获
- 温故而知新:c#中的特性(attribute)
- 温故而知新:new与override的差异以及virtual方法与abstract方法的区别
- malloc函数及用法
- Centos下安装破解confluence6.3的操作记录
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法