倒水问题
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
搜索方向:
- 瓶子往杯子1倒
- 瓶子往杯子2倒
- 杯子1往瓶子倒
- 杯子1往杯子2倒
- 杯子2往瓶子倒
- 杯子2往杯子1倒
一共6个搜索方向
每种情况考虑是否可以倒(是否溢出的情况)溢出时 倒的一方自己还剩多少
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;
struct Node{
int v, v1, v2;//v 可乐 v1 杯子1 v2 杯子2
int step;
};
int m, n, now, next;
int s;
bool vis[105][105][105];
queue<Node> q;
//judge函数 判断是否已经评分
bool judge(Node a){
if((a.v == a.v1 && !a.v2) || (a.v == a.v2 && !a.v1) || (a.v1 == a.v2 && !a.v))
return true;
return false;
}
int bfs(int v){
while(!q.empty()){
q.pop();
}
Node a, b;
// v 为s v1 v2 刚开始为空
a.v = v;
a.v1 = 0;
a.v2 = 0;
a.step = 0;
memset(vis, false, sizeof(vis));
vis[a.v][a.v1][a.v2] = true;
q.push(a);
while(!q.empty()){
a = q.front();
q.pop();
if(judge(a)) return a.step;
//start
//1.first
//第一个杯子没有满
if(a.v1!=n){
//把瓶子里面的倒到第一个杯子里 第一个杯子倒满
if(a.v){
b.v1 = n;
b.v = a.v - n + a.v1;
b.v2 = a.v2;
if(!vis[b.v][b.v1][b.v2]){
vis[b.v][b.v1][b.v2] = true;
b.step = a.step + 1;
q.push(b);
}
}
//把第二个杯子里面的倒到第一个杯子里面
if(a.v2){
b.v = a.v;
//v2倒到第一个杯子里面可能会满出
if(a.v2 + a.v1 > n){
b.v1 = n;
b.v2 = a.v2 - (n - a.v1);
}
else{
b.v1 = a.v1 + a.v2;
b.v2 = 0;
}
if(!vis[b.v][b.v1][b.v2]){
vis[b.v][b.v1][b.v2] = true;
b.step = a.step + 1;
q.push(b);
}
}
}
//2ed
//第二个杯没满
if(a.v2!=m){
//把瓶子里面的倒到第2个杯子里 第2个杯子倒满
if(a.v){
b.v2 = m;
b.v = a.v - m + a.v2;
b.v1 = a.v1;
if(!vis[b.v][b.v1][b.v2]){
vis[b.v][b.v1][b.v2] = true;
b.step = a.step + 1;
q.push(b);
}
}
//把第1个杯子里面的倒到第2个杯子里面
if(a.v1){
b.v = a.v;
//v1倒到第2个杯子里面可能会满出
if(a.v2 + a.v1 > m){
b.v2 = m;
b.v1 = a.v1 - (m - a.v2);
}
else{
b.v2 = a.v2 + a.v1;
b.v1 = 0;
}
if(!vis[b.v][b.v1][b.v2]){
vis[b.v][b.v1][b.v2] = true;
b.step = a.step + 1;
q.push(b);
}
}
}
//3
//瓶子没有满 向瓶子到可乐
if(a.v != s){
//第一个瓶子里面有可乐 就到第一个瓶子里面的
if(a.v1){
b.v = a.v + a.v1;
b.v1 = 0;
b.v2 = a.v2;
if(!vis[b.v][b.v1][b.v2]){
b.step = a.step + 1;
vis[b.v][b.v1][b.v2] = true;
q.push(b);
}
}
//第二个杯子到到瓶子里
if(a.v2){
b.v = a.v + a.v2;
b.v2 = 0;
b.v1 = a.v1;
if(!vis[b.v][b.v1][b.v2]){
b.step = a.step + 1;
vis[b.v][b.v1][b.v2] = true;
q.push(b);
}
}
}
}
return -1;
}
int main(){
while(~scanf("%d%d%d", &s, &n, &m)){
if(!s && !n && !m) break;
if(s%2 == 1){
cout << "NO" << endl;
continue;
}
int step = bfs(s);
if(step == -1)
cout << "NO" << endl;
else cout << step << endl;
}
return 0;
}