HDU 1495 非常可乐【BFS】

HDU 1495 非常可乐

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

题目来源
类似题目:一道类似的倒水题目 POJ 3414

题目思路:
bfs搜索6中可能性

代码:

//hdu 1495
#include<iostream>
#include<queue>
#include<string>
using namespace std;
int s, m, n;
struct Node {
	int ls,lm, ln;	//表示三个容器中剩余水量
	int found;
	int cnt;
	Node(int s, int m, int n, int cnt) {
		this->ls = s, this->lm = m, this->ln = n, this->cnt = cnt;
	}
};
const int INF = 1e5;
int visit[101][101][101];
int found;
void bfs()
{
	for (int i = 0; i <= s; i++)
		for (int j = 0; j <= m; j++)
			for (int k = 0; k <= n; k++)
				visit[i][j][k] = 0;
	queue<Node> q;
	found = 0;	//初始化没找到
	visit[s][0][0] = 1;
	Node node(s, 0, 0, 0);
	q.push(node);
	while (!q.empty())
	{
		Node t = q.front();
		q.pop();
		if (found || t.ls == t.lm && t.ln==0 || t.lm == t.ln && t.ls==0|| t.ln == t.ls &&t.lm==0) {
			found = 1;
			printf("%d\n", t.cnt);
			return;
		}
		//下方的6个if语句可以写成循环,看了别人的题解才发现
		//int ds[6] = {0, 0, 1, 1, 2, 2};
		//int de[6] = { 1, 2, 0, 2, 0, 1 };
		//turn[i]表示ds->de,从一个杯子倒到另一个杯子
		int ts, tm, tn;
		if (t.ls != 0)
		{
			//s->m
			tm = (t.ls + t.lm) / m ? m : t.ls + t.lm;
			ts = (t.ls + t.lm) / m ? t.ls + t.lm - m : 0;
			tn = t.ln;
			if (!visit[ts][tm][tn] && ts >= 0 && ts <= s && tm >= 0 && tm <= m && tn >= 0 && tn <= n) {
				visit[ts][tm][tn] = 1;
				q.push(Node(ts, tm, tn, t.cnt + 1));
			}
			//s->n
			tn = (t.ls + t.ln) / n ? n : t.ls + t.ln;
			ts = (t.ls + t.ln) / n ? t.ls + t.ln - n : 0;
			tm = t.lm;
			if (!visit[ts][tm][tn] && ts >= 0 && ts <= s && tm >= 0 && tm <= m &&tn >= 0 && tn <= n) {
				visit[ts][tm][tn] = 1;
				q.push(Node(ts, tm, tn, t.cnt + 1));
			}
		}
		if (t.lm != 0)
		{
			//m->s
			tm = 0, ts = t.ls + t.lm;
			tn = t.ln;
			if (!visit[ts][tm][tn] && ts >= 0 && ts <= s && tm >= 0 && tm <= m && tn >= 0 && tn <= n) {
				visit[ts][tm][tn] = 1;
				q.push(Node(ts, tm, tn, t.cnt + 1));
			}
			//m->n
			tn = (t.lm + t.ln) / n ? n : t.lm + t.ln;
			tm = (t.lm + t.ln) / n ? t.lm + t.ln - n : 0;
			ts = t.ls;
			if (!visit[ts][tm][tn] && ts >= 0 && ts <= s && tm >= 0 && tm <= m && tn >= 0 && tn <= n) {
				visit[ts][tm][tn] = 1;
				q.push(Node(ts, tm, tn, t.cnt + 1));
			}
		}
		if (t.ln != 0)
		{
			//n->s
			tn = 0, ts = t.ls + t.ln;
			tm = t.lm;
			if (!visit[ts][tm][tn] && ts >= 0 && ts <= s && tm >= 0 && tm <= m && tn >= 0 && tn <= n) {
				visit[ts][tm][tn] = 1;
				q.push(Node(ts, tm, tn, t.cnt + 1));
			}
			//n->m
			tm = (t.ln + t.lm) / m ? m : t.ln + t.lm;
			tn = (t.lm + t.ln) / m ? t.lm + t.ln - m : 0;
			ts = t.ls;
			if (!visit[ts][tm][tn] && ts >= 0 && ts <= s && tm >= 0 && tm <= m && tn >= 0 && tn <= n) {
				visit[ts][tm][tn] = 1;
				q.push(Node(ts, tm, tn, t.cnt + 1));
			}
		}
	}
}
int main()
{
	while (cin >> s >> m >> n, s, m, n)
	{
		bfs();
		if (!found)printf("NO\n");
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值