题目来源: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
扫描二维码关注公众号,回复:
1808917 查看本文章
样例输出
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
}