nyoj21 三个水杯

原题链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=21


//用三维数组的小标记录已经出现过的状态如6 0 0 记vis[6][0][0]=true;
//而每种状态都有6种倒水的方法(1->2 1->3 2->1 2->3 3->1 3->2)倒水的次数=上一个状态次数+1 
//每种方法都可能出现新状态,标记每次出现的新状态,而且第一次出现的新状态也是倒水的次数最少的 
//再用出现的新状态用同样的6种方法循环,直到出现要找的状态或者没有新状态出现为止 
#include <cstdio>
#include <cstring>
#include <queue>
#define min(a, b) a < b ? a : b
using namespace std;
struct Stav{
	int sv[3];	//存每次倒水后3杯水的状态 
	int step;	//记录第一次出现某种状态的次数 
} s;
int V[3], E[3];	//分别存杯子的大小和要求的状态 
bool vis[101][101][101];
int bfs(){
	int i, j, m;
	memset(vis, false, sizeof(vis));	
	queue<Stav > que;
	que.push(s);
	Stav t, r;
	vis[s.sv[0]][0][0] = true;
	while(!que.empty()){
		t = que.front();
		if(t.sv[0] == E[0] && t.sv[1] == E[1] && t.sv[2] == E[2])	//达到要求的状态 
			return t.step;
		//printf("s(%d,%d,%d) step=%d\n",t.sv[0], t.sv[1], t.sv[2], t.step);
		for(i = 0;i < 3;i ++){ //每种状态六种情况 
			for(j = 0;j < 3;j ++){
				if(i != j){	//从第i杯倒入第j杯分两种情况:1 j杯被倒满,如果i杯中剩余的水大于第j杯剩余的空间 
							//							  2 j被没被倒满,如果i杯中剩余的水小于第j杯剩余的空间 
					m = min(t.sv[i], V[j] - t.sv[j]);	//i杯中剩余的水与j杯剩余的空间取较小者从i倒入j(包含了上面两种情况) 
					r = t;
					r.sv[j] += m;	//倒水 
					r.sv[i] -= m;
					r.step = t.step + 1;
					//if(!vis[r.sv[0]][r.sv[1]][r.sv[2]]) printf("-"); else printf(" ");
					//printf("m=%d (%d,%d,%d) step=%d\n", m, r.sv[0], r.sv[1], r.sv[2], r.step);
					if(!vis[r.sv[0]][r.sv[1]][r.sv[2]]){
						
						que.push(r);
						vis[r.sv[0]][r.sv[1]][r.sv[2]] = true;
					}
				}
			}
		}
		//printf("\n");
		que.pop();
	}
	return -1;
} 
int main(){
	int N;
	scanf("%d", &N);
	while(N --){
		scanf("%d%d%d", &V[0], &V[1], &V[2]);
		s.sv[0] = V[0];
		s.sv[1] = s.sv[2] = s.step = 0;
		scanf("%d%d%d", &E[0], &E[1], &E[2]);
		printf("%d\n", bfs());
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值