三个水杯
时间限制:
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
来源
- 经典题目 上传者
分析:
水杯没有标识,用杯子 x 给 y 倒水时必须一直持续把 y 倒满或者把 x 倒空,不能中途停止。
这里我们给三个杯子分别编号为 1, 2, 3。用结构体记录状态,保存在队列中。
V[i] 表示编号为 i 的杯子的体积, E[i] 记录目标状态。
t[i] 表示当前状态编号为 i 的杯子里的水。
详见代码:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<queue> using namespace std; struct State { int c[4], cnt; }; State Begin, cur; queue<State> Q; int vis[100][100], V[4], E[4], Imin; int t[4], tcn, ok; void push() { Begin.c[1] = t[1]; Begin.c[2] = t[2]; Begin.c[3] = t[3]; Begin.cnt = tcn; Q.push(Begin); //新状态,进队列 vis[t[1]][t[2]] = 1; //此状态标记为已经出现 } void Dao(int x, int y) { t[6 - x - y] = cur.c[6 - x - y]; //剩下的杯子里水的体积不变 if(V[y] - cur.c[y] >= cur.c[x]){ //x 向 y 倒,将 x 倒空 t[x] = 0; t[y] = cur.c[x] + cur.c[y]; if(!vis[t[1]][t[2]]) push(); //此状态还未出现 } else{ //将 y 倒满 t[x] = cur.c[x] - (V[y] - cur.c[y]); t[y] = V[y]; if(!vis[t[1]][t[2]]) push(); } } void bfs() { Begin.c[1] = V[1]; Begin.c[2] = Begin.c[3] = Begin.cnt = 0; //初始状态,最大杯子满,其余空 Q.push(Begin); while(!Q.empty()){ cur = Q.front(); Q.pop(); //取队列首元素,取后舍弃 t[1] = cur.c[1], t[2] = cur.c[2], t[3] = cur.c[3], tcn = cur.cnt; if(t[1] == E[1] && t[2] == E[2] && t[3] == E[3] && tcn < Imin) { //达到目标状态,次数又小 ok = 1; Imin = tcn; } tcn = cur.cnt + 1; //次数加 1 if(cur.c[1] > 0){ //1 号杯子向 2, 3 号杯子倒 Dao(1, 2); Dao(1, 3); } if(cur.c[2] > 0){ Dao(2, 1); Dao(2, 3); } if(cur.c[3] > 0){ Dao(3, 1); Dao(3, 2); } } } int main() { //freopen("in.txt", "r", stdin); int t; scanf("%d", &t); while(t--){ memset(vis, 0, sizeof(vis)); Imin = 999999; ok = 0; scanf("%d%d%d%d%d%d", &V[1], &V[2], &V[3], &E[1], &E[2], &E[3]); bfs(); if(ok) printf("%d\n", Imin); else printf("-1\n"); } return 0; }
vis 数组标记状态是否已经出现,这里用二维就够了。如果前两个杯子里的水相同的话,则第三个杯子里的水一定相同!
-
第一行一个整数N(0<N<50)表示N组测试数据