hdu1459_非常可乐
题目大意:
有一杯满可乐,容量为S个单位,另外有两个空杯子,容量分别为N,M。寻问是否存在一种杯的方法,使得在两个杯子,各有S/2的容量。如果存在,请输出你倒的最少次数。
题目测试数据与数据范围:
7 4 3 4 1 3 0 0 0
NO 3
很明显对于 S%2==1 的无法分出半杯,可直接输出NO,而对于 4 1 3,可采取(4,0,0)->(1,0,3)->(1,1,2)->(2,0,2).共三步。
其中 0<S<101 且 S==N+M;
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1495
题目分析:
首先可以确定这是从一个状态转移到另一个状态,初如状态为 (S,0,0) ,目标状态为 (S/2,S/2,0) 或者(S/2,0,S/2);而对于一个状态要发生变化,总共可有六种倒的方法,S->N,S->M,N->S,N->M,M->S,M->N; 对于第一种状态它的下一层次最多为六次,因为可能会存在有重复的状态。所以我们确定这一题是可以用广度优先搜索解决的。但是如何去重呢?要用一个三维数组去标记吗?我们知道,当两个杯子的状态都确定的时候,第三个也就一定确定了,所以用一个二维就够了。所以,在我看来,这又只是一道广度优先搜索的模板题。但其中还真的有一些细节需要你去注意,不注意,很容易出现意想不到的结果,有时候结果都不会出现。因为我们是枚举任意两个杯子相互之间倒水,很容易把第三个没有操作的杯子给忽略。!!!!。
小乐一下:
结点进入队列
(是否要标记起点(优先队列))
进入循环(){
一个结点出队,
(要判断这个是不是目标点吗?)
对于这个可扩展的结点入队(是否要标记)
在扩展的时候(一个状态的所在属性要确保有值),碰到目标点,是进队还是直接返回结束。
}
循环里没有返回,表示没有搜索到目标点,返回-1表示失败。
对于队列,我们有时要考虑自己写的队列,这样有两个好处,其一,可以防止爆栈,其二,在要打印路径的时候,很容易且很有效果。
代码,更好更简洁的由你来实现,不要直接复制。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 105
int vis[maxn][maxn],cap[3],target;
struct Node{int v[3];int fa,dist;
};
Node q[maxn*maxn]; //相当于自己定义的一个队列。
int mins(int a,int b){return a<b?a:b;}void print_path(int idx){ //这个是打印路径。if(q[idx].fa != idx) print_path(q[idx].fa);printf("%d %d %d\n",q[idx].v[0],q[idx].v[1],q[idx].v[2]);
}int bfs(){int front = 0,rear = 0;int i,j;Node cur,next;q[0].v[0] = cap[0];q[0].v[1] = q[0].v[2] = q[0].dist = 0;q[0].fa = 0;vis[cap[0]][0] = 1;while(front<=rear){cur = q[front];int cnt = 0;if(cur.v[0] == target) cnt++;if(cur.v[1] == target) cnt++;if(cur.v[2] == target) cnt++;if(cnt>=2 ){//print_path(front); //达到目标点了,该返回了。return cur.dist;}for(i = 0;i<3;i++){for(j = 0;j<3;j++)if(i!=j){int temp = mins(cur.v[i],cap[j]-cur.v[j]);for(int k = 0;k<3;k++) next.v[k] = cur.v[k]; //为了防止我们忽略那个没有进行操作的杯子。next.v[i] -= temp; //<span style="font-family: Arial, Helvetica, sans-serif;">我们还是先把该有的属性先填上一个与上一个状态有联系的值吧。</span>next.v[j] += temp;if(!vis[next.v[0]][next.v[1]]){vis[next.v[0]][next.v[1]] = 1;next.dist = cur.dist+ 1;next.fa = front;q[++rear] = next;}}}front ++;}return -1;
}
int main(){int i,j;while(scanf("%d%d%d",&cap[0],&cap[1],&cap[2])!=EOF){if(cap[0]+cap[1]+cap[2]==0) break;if(cap[0]%2) {printf("NO\n");continue;}target = cap[0]/2;memset(vis,0,sizeof(vis));int ans = bfs();if(ans != -1) printf("%d\n",ans);else printf("NO\n");}return 0;
}
伟大的梦想成就伟大的人,从细节做好,从点点滴滴做好,从认真做好。
hdu1459_非常可乐相关推荐
- M - 非常可乐 HDU - 1495
M - 非常可乐 HDU - 1495 一个简单的 bfs 被我写的又臭又长 如果修改的话,建议把倒水判断的部分直接改为 now.s+nown <= S 即可 #include<iostr ...
- hdu 1495 非常可乐 (bfs)
非常可乐 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...
- 【HDU1495非常可乐】【POJ3414Pots】
HDU1495非常可乐 大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为.因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要喝的和se ...
- HDU 1495 非常可乐
非常可乐 http://acm.hdu.edu.cn/showproblem.php?pid=1495 Time Limit: 2000/1000 MS (Java/Others) Memory ...
- HDU1495 非常可乐
问题链接:HDU1495 非常可乐. 题意简述:平分液体问题.输入s.n和m三个数,分别代表可乐和2个杯子,三个容器可以互相倒,问能不能把s中的可乐平分,能的话输出最小倒杯子的次数,不能就输出NO. ...
- 题目1457:非常可乐(广度优先遍历BFS)
题目链接:http://ac.jobdu.com/problem.php?pid=1457 详解链接:https://github.com/zpfbuaa/JobduInCPlusPlus 参考代码: ...
- HDU - 1495 - 非常可乐
先上题目: 非常可乐 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- 杭电1495非常可乐
非常可乐 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...
- HDU1495 非常可乐【倒水问题+BFS】
非常可乐 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...
最新文章
- docker远程访问TLS证书认证shell
- javascript特效_如何在网页添加鼠标点击特效
- King Arthur
- python决策树预测模型_带决策树回归模型的负交叉值得分
- Avalondock 第三步 创建停靠面板组
- 计算机添加usb网络打印机,方便实用!教您如何简单地将USB打印机更改为无线打印机!...
- php 金额转大写,php实现将人民币金额转大写的办法
- 卡方检验四格表怎么做_运用SPSS进行医学诊断数据的Kappa一致性检验 ——【杏花开医学统计】...
- 欧盟斥资18亿欧元 砸向网络安全领域——英国,你后悔了没?
- openwrt 无线基础知识介绍
- Xcode如何实现iphone真机测试
- Fiddler调式使用(一)深入研究[转载]
- Mercury mw150us(8188eu) debian wireless driver
- 《区块链技术与应用》北大肖臻老师——课程笔记【21-23】
- JMU软件计组期末复习总结
- 图像特征点、投影变换与图像拼接
- POS打印机制造商容大科技筹备A股上市,许开明合计持股约90%
- 书,是人类进步的阶梯。当当购书优惠码限时抢!
- win7 exfat补丁_微信内测版,Win7停更?你知道吗?(内有福利)
- 如何快速掌握正确的UI配色方案?6种技巧不容错过!