nyoj21 三个水杯(搜索)

题目来源:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=21

三个水杯

时间限制:1000 ms |  内存限制:65535 KB

难度:4

描述

给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子。三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算。现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数。

输入

第一行一个整数N(0<N<50)表示N组测试数据
接下来每组测试数据有两行,第一行给出三个整数V1 V2 V3 (V1>V2>V3 V1<100 V3>0)表示三个水杯的体积。
第二行给出三个整数E1E2 E3 (体积小于等于相应水杯体积)表示我们需要的最终状态

输出

每行输出相应测试数据最少的倒水次数。如果达不到目标状态输出-1

样例输入

2
6 3 1
4 1 1
9 3 2
7 1 1

样例输出

3

-1

 -----------------------------------------------------

思路

解空间的无权最短路问题。

三个水杯当前含水量构成一个状态为解空间的节点,一次倒水为解空间的一条边。求解从固定起点到给定终点的最短路。由于边无权,故用广度优先搜索求解。

注意起点和终点相同时的特殊处理。

-----------------------------------------------------

代码

// 解空间广度优先搜索求最短路

#include<iostream>
#include<fstream>
#include<cstring>
#include<queue>
using namespace std;

struct state {
	int s1,s2,s3;				// 3个水杯里的含量
	int cnt;					// 从开始到这一步用了几步操作

	state(int ss1, int ss2, int ss3, int mycnt):s1(ss1), s2(ss2), s3(ss3), cnt(mycnt){}
};

const int NMAX = 105;
int v1,v2,v3;					// 全局变量:杯子容量
bool mat[NMAX][NMAX][NMAX] = {};// 状态图矩阵,访问过为1,没有访问过为0
int bfs(int b1, int b2, int b3, int e1, int e2, int e3)
{
	if (b1==e1 && b2==e2 && b3==e3)
	{
		return 0;
	}
	memset(mat,0,sizeof(mat));	// 状态图标记清空
	queue<state> qs;			// 广搜队列
	state s0(b1,b2,b3,0);		// 初始状态
	qs.push(s0);				// 初始状态入队
	mat[b1][b2][b3] = 1;		// 在状态图上标记初始状态
	int ss1,ss2,ss3,sp1,sp2,sp3;
	while (!qs.empty())			// 当队列不空
	{
		s0 = qs.front();		// 取队首元素
		qs.pop();				// 弹出队首元素
		// 遍历6种互相倒水的情况
		ss1 = s0.s1;
		ss2 = s0.s2;
		ss3 = s0.s3;
		if (ss2 < v2 && ss1 > 0)	// 1 -> 2
		{
			if (ss1>=(v2-ss2))
			{
				sp1 = ss1-v2+ss2;
				sp2 = v2;
				sp3 = ss3;
				if (sp1==e1 && sp2==e2 && sp3==e3)
				{
					return s0.cnt+1;
				}
				if (!mat[sp1][sp2][sp3])
				{
					state s1(sp1, sp2, sp3, s0.cnt+1);
					qs.push(s1);
					mat[sp1][sp2][sp3] = 1;
				}
			}
			else
			{
				sp1 = 0;
				sp2 = ss2+ss1;
				sp3 = ss3;
				if (sp1==e1 && sp2==e2 && sp3==e3)
				{
					return s0.cnt+1;
				}
				if (!mat[sp1][sp2][sp3])
				{
					state s1(sp1, sp2, sp3, s0.cnt+1);
					qs.push(s1);
					mat[sp1][sp2][sp3] = 1;
				}
			}
		}
		if (ss3 < v3 && ss1 > 0)	// 1 -> 3
		{
			if (ss1>=(v3-ss3))
			{
				sp1 = ss1-v3+ss3;
				sp2 = ss2;
				sp3 = v3;
				if (sp1==e1 && sp2==e2 && sp3==e3)
				{
					return s0.cnt+1;
				}
				if (!mat[sp1][sp2][sp3])
				{
					state s1(sp1, sp2, sp3, s0.cnt+1);
					qs.push(s1);
					mat[sp1][sp2][sp3] = 1;
				}
			}
			else
			{
				sp1 = 0;
				sp2 = ss2;
				sp3 = ss3+ss1;
				if (sp1==e1 && sp2==e2 && sp3==e3)
				{
					return s0.cnt+1;
				}
				if (!mat[sp1][sp2][sp3])
				{
					state s1(sp1, sp2, sp3, s0.cnt+1);
					qs.push(s1);
					mat[sp1][sp2][sp3] = 1;
				}
			}
		}
		if (ss1 < v1 && ss2 > 0)	// 2 -> 1
		{
			if (ss2>=(v1-ss1))
			{
				sp1 = v1;
				sp2 = ss2-v1+ss1;
				sp3 = ss3;
				if (sp1==e1 && sp2==e2 && sp3==e3)
				{
					return s0.cnt+1;
				}
				if (!mat[sp1][sp2][sp3])
				{
					state s1(sp1, sp2, sp3, s0.cnt+1);
					qs.push(s1);
					mat[sp1][sp2][sp3] = 1;
				}
			}
			else
			{
				sp1 = ss1+ss2;
				sp2 = 0;
				sp3 = ss3;
				if (sp1==e1 && sp2==e2 && sp3==e3)
				{
					return s0.cnt+1;
				}
				if (!mat[sp1][sp2][sp3])
				{
					state s1(sp1, sp2, sp3, s0.cnt+1);
					qs.push(s1);
					mat[sp1][sp2][sp3] = 1;
				}
			}
		}
		if (ss3 < v3 && ss2 > 0)	// 2 -> 3
		{
			if (ss2>=(v3-ss3))
			{
				sp1 = ss1;
				sp2 = ss2-v3+ss3;
				sp3 = v3;
				if (sp1==e1 && sp2==e2 && sp3==e3)
				{
					return s0.cnt+1;
				}
				if (!mat[sp1][sp2][sp3])
				{
					state s1(sp1, sp2, sp3, s0.cnt+1);
					qs.push(s1);
					mat[sp1][sp2][sp3] = 1;
				}
			}
			else
			{
				sp1 = ss1;
				sp2 = 0;
				sp3 = ss3+ss2;
				if (sp1==e1 && sp2==e2 && sp3==e3)
				{
					return s0.cnt+1;
				}
				if (!mat[sp1][sp2][sp3])
				{
					state s1(sp1, sp2, sp3, s0.cnt+1);
					qs.push(s1);
					mat[sp1][sp2][sp3] = 1;
				}
			}
		}
		if (ss1 < v1 && ss3 > 0)	// 3 -> 1
		{
			if (ss3>=(v1-ss1))
			{
				sp1 = v1;
				sp2 = ss2;
				sp3 = ss3-v1+ss1;
				if (sp1==e1 && sp2==e2 && sp3==e3)
				{
					return s0.cnt+1;
				}
				if (!mat[sp1][sp2][sp3])
				{
					state s1(sp1, sp2, sp3, s0.cnt+1);
					qs.push(s1);
					mat[sp1][sp2][sp3] = 1;
				}
			}
			else
			{
				sp1 = ss1+ss3;
				sp2 = ss2;
				sp3 = 0;
				if (sp1==e1 && sp2==e2 && sp3==e3)
				{
					return s0.cnt+1;
				}
				if (!mat[sp1][sp2][sp3])
				{
					state s1(sp1, sp2, sp3, s0.cnt+1);
					qs.push(s1);
					mat[sp1][sp2][sp3] = 1;
				}
			}
		}
		if (ss2 < v2 && ss3 > 0)	// 3 -> 2
		{
			if (ss3>=(v2-ss2))
			{
				sp1 = ss1;
				sp2 = v2;
				sp3 = ss3-v2+ss2;
				if (sp1==e1 && sp2==e2 && sp3==e3)
				{
					return s0.cnt+1;
				}
				if (!mat[sp1][sp2][sp3])
				{
					state s1(sp1, sp2, sp3, s0.cnt+1);
					qs.push(s1);
					mat[sp1][sp2][sp3] = 1;
				}
			}
			else
			{
				sp1 = ss1;
				sp2 = ss2+ss3;
				sp3 = 0;
				if (sp1==e1 && sp2==e2 && sp3==e3)
				{
					return s0.cnt+1;
				}
				if (!mat[sp1][sp2][sp3])
				{
					state s1(sp1, sp2, sp3, s0.cnt+1);
					qs.push(s1);
					mat[sp1][sp2][sp3] = 1;
				}
			}
		}
	}
	return -1;
}

int main()
{
#ifndef ONLINE_JUDGE
	ifstream fin ("nyoj21.txt");
	int t,e1,e2,e3;
	fin >> t;
	while (t--)
	{
		fin >> v1 >> v2 >> v3 >> e1 >> e2 >> e3;
		cout << bfs(v1,0,0,e1,e2,e3) << endl;
	}
	fin.close();
#endif
#ifdef ONLINE_JUDGE
	int t,e1,e2,e3;
	cin >> t;
	while (t--)
	{
		cin >> v1 >> v2 >> v3 >> e1 >> e2 >> e3;
		cout << bfs(v1,0,0,e1,e2,e3) << endl;
	}
#endif
}


猜你喜欢

转载自blog.csdn.net/da_kao_la/article/details/80855582