HDU 1495 非常可乐 【BFS + 倒水问题】

倒水问题
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. 瓶子往杯子1倒
  2. 瓶子往杯子2倒
  3. 杯子1往瓶子倒
  4. 杯子1往杯子2倒
  5. 杯子2往瓶子倒
  6. 杯子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;
}



  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值