HDOJ1495 非常可乐(bfs)

题目链接:点击打开链接


定义结构体保存当前状态的m, n, s杯中的可乐,t表示倒可乐次数。读入m, n, s后保证m < n < s便于bfs,接下来就是6个方向的bfs。

bfs结束的条件是m杯中无可乐,也就是当前n杯的可乐与当前s杯的可乐相等,且n杯的可乐为总可乐体积的一半。接下来就是s倒入

m,s倒入n,m倒入n,n倒入m,m倒入s,n倒入s的6种情况,如果不满足题意最后则输出NO。


AC代码:

#include "iostream"
#include "cstdio"
#include "cstring"
#include "algorithm"
#include "queue"
using namespace std;
const int MAXN = 105;
int s, n, m;
bool vis[MAXN][MAXN];
struct node
{
	/* data */
	int m, n, s, t;
};
void bfs()
{
	queue<node> q;
	memset(vis, false, sizeof(vis));
	node x, y;
	x.m = x.n = x.t = 0, x.s = s;
	q.push(x);
	vis[x.m][x.n] = true;
	while(!q.empty()) {
		x = q.front();
		q.pop();
		if(x.n == x.s && x.n == s/ 2) {
			printf("%d\n", x.t);
			return ;
		}
		if(x.s + x.m > m) { // s倒入m
			y.m = m, y.n = x.n, y.s = x.s + x.m - m, y.t = x.t + 1;
			if(!vis[y.m][y.n]) {
				q.push(y);
				vis[y.m][y.n] = true;
			}
		}
		else {
			y.m = x.s + x.m, y.n = x.n, y.s = 0, y.t = x.t + 1;
			if(!vis[y.m][y.n]) {
				q.push(y);
				vis[y.m][y.n] = true;
			}
		}
		if(x.s + x.n > n) { // s倒入n
			y.m = x.m, y.n = n, y.s = x.s + x.n - n, y.t = x.t + 1;
			if(!vis[y.m][y.n]) {
				q.push(y);
				vis[y.m][y.n] = true;
			}
		}
		else {
			y.m = 0, y.n = x.s + x.n - n, y.s = 0, y.t = x.t + 1;
			if(!vis[y.m][y.n]) {
				q.push(y);
				vis[y.m][y.n] = true;
			}
		}
		if(x.m + x.n > n) { // m倒入n
			y.m = x.m + x.n - n, y.n = n, y.s = x.s, y.t = x.t + 1;
			if(!vis[y.m][y.n]) {
				q.push(y);
				vis[y.m][y.n] = true;
			}
		}
		else {
			y.m = 0, y.n = x.m + x.n, y.s = x.s, y.t = x.t + 1;
			if(!vis[y.m][y.n]) {
				q.push(y);
				vis[y.m][y.n] = true;
			}
		}
		if(x.m + x.n > m) { // n倒入m
			y.n = x.n + x.m - m, y.m = m, y.s = x.s, y.t = x.t + 1;
			if(!vis[y.m][y.n]) {
				q.push(y);
				vis[y.m][y.n] = true;
			}
		}
		else {
			y.m = x.m + x.n, y.n = 0, y.s = x.s, y.t = x.t + 1;
			if(!vis[y.m][y.n]) {
				q.push(y);
				vis[y.m][y.n] = true;
			}
		}
		y.s = x.s + x.m, y.m = 0, y.n = x.n, y.t = x.t + 1; // m倒入s
		if(!vis[y.m][y.n]) {
				q.push(y);
				vis[y.m][y.n] = true;
			}
		y.s = x.s + x.n, y.m = x.m, y.n = 0, y.t = x.t + 1; // n倒入s
		if(!vis[y.m][y.n]) {
				q.push(y);
				vis[y.m][y.n] = true;
			}
	}
	printf("NO\n");
}
int main(int argc, char const *argv[])
{
	while(scanf("%d%d%d", &s, &m, &n) != EOF && s) {
		if(s & 1) {
			printf("NO\n");
			continue;
		}
		if(m > n) swap(m, n);
		bfs();
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值