NYOJ21 三个水杯 【BFS】

三个水杯

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 4
描述
给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子。三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算。现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数。
输入
第一行一个整数N(0<N<50)表示N组测试数据
接下来每组测试数据有两行,第一行给出三个整数V1 V2 V3 (V1>V2>V3 V1<100 V3>0)表示三个水杯的体积。
第二行给出三个整数E1 E2 E3 (体积小于等于相应水杯体积)表示我们需要的最终状态
输出
每行输出相应测试数据最少的倒水次数。如果达不到目标状态输出-1
样例输入
2
6 3 1
4 1 1
9 3 2
7 1 1
样例输出
3
-1

很经典的广搜题,昨天去参加省赛时队友还把这题给打印出来了,足见其经典性。

 //NYOJ21_BFS
#include <stdio.h>
#include <string.h>
#include <queue>
using std::queue;

struct Node{
	int v[3];
	int steps;
} init, targ;
bool vis[100][100][100];

bool del(Node &cup, int start, int end){
	if(cup.v[start] && cup.v[end] != init.v[end]){ //能倒水
		int sum = cup.v[start] + cup.v[end];
		if(sum >= init.v[end]) cup.v[end] = init.v[end];
		else cup.v[end] = sum;
		cup.v[start] = sum - cup.v[end];
		if(!vis[cup.v[0]][cup.v[1]][cup.v[2]])
			return vis[cup.v[0]][cup.v[1]][cup.v[2]] = true;			
	}
	return false;
}

int BFS(){
	Node cup = {init.v[0], 0, 0, 0}, temp;
	queue<Node> Q;
	memset(vis, 0, sizeof(vis));
	
	vis[init.v[0]][0][0] = true;
	Q.push(cup);
	
	while(!Q.empty()){
		temp = cup = Q.front();
		if(temp.v[0] == targ.v[0] && temp.v[1] == targ.v[1]
			&& temp.v[2] == targ.v[2]) return temp.steps;
		Q.pop();
		for(int i = 0; i < 3; ++i){			
			for(int j = 0; j < 3; ++j){
				temp = cup;
				if(i != j && del(temp, i, j)){					
					++temp.steps;					
					Q.push(temp);		
				}
			}
		}
	}
	return -1;
}

int main(){
	int t;
	scanf("%d", &t);
	while(t--){
		scanf("%d%d%d", init.v, init.v + 1, init.v + 2);
		scanf("%d%d%d", targ.v, targ.v + 1, targ.v + 2);
		printf("%d\n", BFS());
	}
	return 0;
}        


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值