题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1495

非常可乐

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 16814    Accepted Submission(s): 6805

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

题解:

1.由于每个容器不超过100, 所以枚举所有状态(1e6)也不会超时。所以直接用BFS。

2.判重:

2.1:其中S<=100,  1<=N<100, 1<=M<100,所以可以将当前三个容器的可乐量压缩成一个int类型,且最大不超过1009999(S放在前面,如果放在中间或者后面,就要加多一位了,这里有讲究),然后就可以开个vis[]数组直接检查状态status是否已经访问过了。

2.2:其实不用把三个容器压缩成一个int类型,可以直接开个三维数组vis[110][110][110],每一维对应一个容器,也是1e6级别的大小,而且更加方便灵活。

2.3:其实开二维数组就够了,因为总的可乐量是确定的,当其中两个容器的可乐量确定了,那剩下的容器的可乐量也就确定了。这一个简单的优化又把内存消耗降低了100倍。

关于判重,目前自己有三个习惯的方法:STL的set、vis多维判重 与 vis status(int类型的以为判重)  。

1. set判重,适用状态高度离散的判重(开数组不能满足其范围), 特点慢,能用数组判重就尽量不要用set判重。

2.vis多维判重, 适用于状态集中且维度较少的情况。

3.staus判重,适用于状态集中且维度较多的情况, 其本质就是把所有维度的状态都压缩成一个int类型, 所以status本质是一个哈希值。

2.1(status判重):

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXN = 2e6+; //0为容器S, 1为容器N, 2为容器M
struct node
{
int status, con[], step; //con[i]为容器i当前盛的可乐体积
};
int vol[], vis[MAXN]; //vol[i]为容器i的容量 queue<node>que;
int bfs()
{
ms(vis,);
while(!que.empty()) que.pop(); node now, tmp;
now.con[] = vol[]; //初始状态只用容器S盛有可乐
now.con[] = now.con[] = ;
now.status = vol[]*; //初始的状态
now.step = ;
vis[now.status] = ;
que.push(now); while(!que.empty())
{
now = que.front();
que.pop(); // cout<< now.status <<endl;
if((now.con[]==vol[]/ && now.con[]==vol[]/)
|| (now.con[]==vol[]/ && now.con[]==vol[]/)
|| (now.con[]==vol[]/ && now.con[]==vol[]/))
return now.step; for(int i = ; i<; i++) //模拟倒水的过程, i为倒, j为被倒
for(int j = ; j<; j++)
{
if(i==j) continue;
tmp = now;
int pour = min(tmp.con[i], vol[j]-tmp.con[j]); //能倒多少水
tmp.con[j] += pour;
tmp.con[i] -= pour;
tmp.status = tmp.con[]*+tmp.con[]*+tmp.con[]; //更新状态
if(!vis[tmp.status])
{
vis[tmp.status] = ;
tmp.step++;
que.push(tmp);
}
}
}
return -;
} int main()
{
while(scanf("%d%d%d",&vol[], &vol[], &vol[]) && (vol[]||vol[]||vol[]))
{
if(vol[]%) //奇数肯定不能平分
{
printf("NO\n");
continue;
}
int ans = bfs();
if(ans==-)
printf("NO\n");
else
printf("%d\n", ans);
}
return ;
}

2.2(三维判重):

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXN = +; struct node
{
int con[], step;
};
int vol[], vis[MAXN][MAXN][MAXN]; queue<node>que;
int bfs()
{
ms(vis,);
while(!que.empty()) que.pop(); node now, tmp;
now.con[] = vol[];
now.con[] = now.con[] = ;
now.step = ;
vis[now.con[]][now.con[]][now.con[]] = ;
que.push(now); while(!que.empty())
{
now = que.front();
que.pop(); if((now.con[]==vol[]/ && now.con[]==vol[]/)
|| (now.con[]==vol[]/ && now.con[]==vol[]/)
|| (now.con[]==vol[]/ && now.con[]==vol[]/))
return now.step; for(int i = ; i<; i++) //模拟倒水的过程
for(int j = ; j<; j++)
{
if(i==j) continue;
tmp = now;
int pour = min(tmp.con[i], vol[j]-tmp.con[j]);
tmp.con[j] += pour;
tmp.con[i] -= pour;
if(!vis[tmp.con[]][tmp.con[]][tmp.con[]])
{
vis[tmp.con[]][tmp.con[]][tmp.con[]] = ;
tmp.step++;
que.push(tmp);
}
}
}
return -;
} int main()
{
while(scanf("%d%d%d",&vol[], &vol[], &vol[]) && (vol[]||vol[]||vol[]))
{
if(vol[]%)
{
printf("NO\n");
continue;
}
int ans = bfs();
if(ans==-)
printf("NO\n");
else
printf("%d\n", ans);
}
return ;
}

2.3(二维判重,推荐使用):

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXN = +; struct node
{
int con[], step;
};
int vol[], vis[MAXN][MAXN]; queue<node>que;
int bfs()
{
ms(vis,);
while(!que.empty()) que.pop(); node now, tmp;
now.con[] = vol[];
now.con[] = now.con[] = ;
now.step = ;
vis[now.con[]][now.con[]] = ;
que.push(now); while(!que.empty())
{
now = que.front();
que.pop(); if((now.con[]==vol[]/ && now.con[]==vol[]/)
|| (now.con[]==vol[]/ && now.con[]==vol[]/)
|| (now.con[]==vol[]/ && now.con[]==vol[]/))
return now.step; for(int i = ; i<; i++) //模拟倒水的过程
for(int j = ; j<; j++)
{
if(i==j) continue;
tmp = now;
int pour = min(tmp.con[i], vol[j]-tmp.con[j]);
tmp.con[j] += pour;
tmp.con[i] -= pour;
if(!vis[tmp.con[]][tmp.con[]])
{
vis[tmp.con[]][tmp.con[]] = ;
tmp.step++;
que.push(tmp);
}
}
}
return -;
} int main()
{
while(scanf("%d%d%d",&vol[], &vol[], &vol[]) && (vol[]||vol[]||vol[]))
{
if(vol[]%)
{
printf("NO\n");
continue;
}
int ans = bfs();
if(ans==-)
printf("NO\n");
else
printf("%d\n", ans);
}
return ;
}

HDU1495 非常可乐 —— BFS + 模拟的更多相关文章

  1. hdu_1495_非常可乐(bfs模拟)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1495 题意:不解释 题解:BFS模拟,不过要细心,把所有情况都列举出来,开一个数组记录状态,代码有点长 ...

  2. BFS+模拟 ZOJ 3865 Superbot

    题目传送门 /* BFS+模拟:dp[i][j][p] 表示走到i,j,方向为p的步数为多少: BFS分4种情况入队,最后在终点4个方向寻找最小值:) */ #include <cstdio&g ...

  3. HDU 1495 非常可乐 BFS搜索

    题意:有个为三个杯子(杯子没有刻度),体积为s,n,m,s=m+n, 刚开始只有体积为s的杯子装满可乐,可以互相倒,问你最少的次数使可乐均分,如果没有结果,输出-1; 分析:直接互相倒就完了,BFS模 ...

  4. Hdu 5336 XYZ and Drops (bfs 模拟)

    题目链接: Hdu 5336 XYZ and Drops 题目描述: 有一个n*m的格子矩阵,在一些小格子里面可能会有一些水珠,每个小水珠都有一个size.现在呢,游戏开始咯,在一个指定的空的小格子里 ...

  5. HDU-1495 非常可乐(BFS)

    广搜的灵活应用题: 非常可乐 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  6. 非常可乐(杭电hdu1495)bfs

      非常可乐 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Sub ...

  7. HDU1495 非常可乐(BFS/数论)

    大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为.因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要喝的和seeyou一样多.但see ...

  8. POJ 3414 Pots【bfs模拟倒水问题】

    链接: http://poj.org/problem?id=3414 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=22009#probl ...

  9. HDU 1495 非常可乐 BFS 搜索

    http://acm.hdu.edu.cn/showproblem.php?pid=1495 题目就不说了, 说说思路! 倒可乐 无非有6种情况: 1. S 向 M 倒 2. S 向 N 倒 3. N ...

随机推荐

  1. Centos 安装Python3的方法

    由于centos7原本就安装了Python2,而且这个Python2不能被删除,因为有很多系统命令,比如yum都要用到. [root@VM_105_217_centos Python-3.6.2]# ...

  2. SHoj A序列

    A序列 发布时间: 2017年7月9日 18:17   最后更新: 2017年7月9日 21:05   时间限制: 1000ms   内存限制: 128M 描述 如果一个序列有奇数个正整数组成,不妨令 ...

  3. FGrowth算法

    一:背景 http://www.cnblogs.com/aijianiula/p/5397857.html 上节中,总结了频繁项集挖掘的最基本算法:Apriori算法.这篇文章写下它的改进算法FGro ...

  4. noj 2069 赵信的往事 [yy题 无限gcd]

    njczy2010 2069 Accepted 31MS   224K 1351Byte G++ 2014-11-13 13:32:56.0 坑爹的无限gcd,,,尼玛想好久,原来要x对y算一次,y再 ...

  5. HDU5056 BoringCount--线性扫一遍

    11754936 2014-09-29 10:08:45 Accepted 5056 31MS 392K 1257 B G++ czy 好简单的思路,怎么就没想到呢..... Boring count ...

  6. Android借助Handler,实现ViewPager中页面的自动切换(转)

    在很多电商网页及app上都有自动切换的商品的推广快,感觉体验挺不错的,正好今天学习使用ViewPager,因此也实现了一个功能类似的demo. 下面是其中的两个截图:           实现一个自动 ...

  7. elasticsearch入门使用(二) Mapping + field type字段类型

    Elasticsearch Reference [6.2] » Mapping 参考官方英文文档 https://www.elastic.co/guide/en/elasticsearch/refer ...

  8. 汉若塔系列续:汉诺塔VIII、汉诺塔IX、汉诺塔X。

    汉诺塔VIII,在经典汉若塔问题上,问n个盘子的情况下,移动m次以后,是什么状态.(与第七代互为逆命题) 我的思路:本质还是dfs,但是用m的值来指引方向,每搜一层确定第i个盘子在哪个塔,o(n)的算 ...

  9. raspi串口、python串口模块pyserial

    一.安装 1.下载软件包pyserial-2.7.tar.gz   网址:https://pypi.python.org/pypi/pyserial 2.8uftp上传至/usr/local/src/ ...

  10. rsync故障排查整理

    1.客户端的错误现象:No route to host rsync服务端开启了iptables防火墙 rsync -avz /etc/hosts rsync_backup@172.16.1.41::b ...