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校园文化活动月”之“校庆杯”大学生程序设计竞赛暨杭州电子科技大学第四届大学生程序设计竞赛
BFS练习题目,顺带熟悉STL的一些用法,这周就从简单搜索和并查集一类基础算法开始,然后搞懂基础的树。多校赛休整四天,希望下次比赛有所提高!
#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
struct node{
int v[4];
int step;
}temp, cnt;
int m[4], book[101][101][101]; //三维数组保存状态
void pour(int a, int b)
{
int sum = temp.v[a] + temp.v[b];
if(sum >= m[b]) //如果会溢出
temp.v[b] = m[b];
else
temp.v[b] = sum;
temp.v[a] = sum - temp.v[b];
}
void bfs()
{
queue <node> p;
cnt.step = 0;
cnt.v[1] = m[1];
cnt.v[2] = cnt.v[3] = 0;
p.push(cnt);
memset(book, 0, sizeof(book));
while(!p.empty())
{
cnt = p.front();
p.pop();
/* push(x) 将x压入队列的末端
pop() 弹出队列的第一个元素(队顶元素),注意此函数并不返回任何值
front() 返回第一个元素(队顶元素)
back() 返回最后被压入的元素(队尾元素)
empty() 当队列为空时,返回true
size() 返回队列的长度 */
if(cnt.v[1] == cnt.v[2] && cnt.v[3] == 0)
{
cout << cnt.step << endl;
return ;
}
for(int i = 1; i < 4; i++)
{
for(int j = 1; j < 4; j++)
{
if(i != j)
{
temp = cnt; //原始水位 6个操作独立存在
pour(i, j);
if(!book[temp.v[1]][temp.v[2]][temp.v[3]])//该状态未存在过
{
book[temp.v[1]][temp.v[2]][temp.v[3]] = 1;//标记存在
temp.step++;
p.push(temp);
}
}
}
}
}
cout << "NO" << endl;
}
int main()
{
std::ios::sync_with_stdio(false);
while(1)
{
cin >> m[1] >> m[2] >> m[3];
if(m[1] == 0 && m[2] == 0 && m[3] == 0)
{
break;
}
if(m[3] > m[2]) //调整顺序则bfs中输出末态可满足
{
int t;
t = m[2];
m[2] = m[3];
m[3] = t;
}
bfs();
}
}