三个水杯
时间限制:
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
-
-
定义某个时刻的的状态为(V0,V1,V2)。用广搜来搜索。
-
-
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <map> #include <stack> #include <queue> #include <set> #include <list> #define LL long long #define INF 0x7fffffff #define FIN 0x80000000 using namespace std; typedef int State[5]; State star, goal; State sta[1000000]; int dis[102][102][102]; // 距离 int solve() { memset(dis, -1, sizeof(dis)); queue<int> que; sta[0][0] = star[0]; sta[0][1] = sta[0][2] = 0; int k = 1; dis[star[0]][0][0] = 0; //开始距离初始为0 que.push(k - 1); while(que.size()) { int u = que.front(); que.pop(); // printf("%d %d %d ###\n", sta[u][0], sta[u][1], sta[u][2]); State &s = sta[u]; if(memcmp(s, goal, sizeof(s)) == 0) return dis[s[0]][s[1]][s[2]]; //倒水 for(int i = 0 ; i < 3 ; i++) for(int j = 0 ; j < 3 ; j++) { if(i != j) //去掉自己倒给自己 { if(s[i] == 0) continue; State &v = sta[k]; memcpy(&v, &s, sizeof(State)); int t = star[j] - s[j]; //j杯子最大倒水量 if(t > s[i]) t = s[i]; //实际倒水量 v[i] -= t; v[j] += t; if(dis[v[0]][v[1]][v[2]] < 0) { dis[v[0]][v[1]][v[2]] = dis[s[0]][s[1]][s[2]] + 1; que.push(k); k++; } } } } return -1; } int main() { int T; scanf("%d", &T); while(T--) { scanf("%d %d %d", &star[0], &star[1], &star[2]); //开始状态 scanf("%d %d %d", &goal[0], &goal[1], &goal[2]); //目标转态 int ans = solve(); if(ans >= 0) printf("%d\n", ans); else printf("-1\n"); } }
-
第一行一个整数N(0<N<50)表示N组测试数据