三个水杯
时间限制:
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
-
广搜的题目~一开始看着没什么思路,后来理解之后就显得简单多了,除了wrong answer之外也就没什么了。
-
主要就是三个水杯互相倒水的问题~
-
-
觉得有了这张图就很好理解了~每次互相倒水,判断出现状态是否重复~
-
-
代码~
-
说下需要注意的地方,也是我丢三落四容易落下的地方:1,标记数组的清空 2,就是队列的设置,要是全局的队列就要记得清空,不想每次都清空酒把队列设成局部的~嗯,就这样!#include <iostream> #include <stdio.h> #include <queue> #include <string.h> using namespace std; struct node { int water[3]; int step; }; int cup[3]; //水杯的容量 int end_water[3]; //结束状态 int vis[101][101][101]; //标记数组 int OK(node succeed) //判断结束 { int i; for(i=0; i<3; i++) { if(succeed.water[i] != end_water[i]) return 0; } return 1; } int bfs() { queue <node> Q; memset(vis, 0, sizeof(vis)); //要注意标记数组的清空 node start, p, q; start.water[0] = cup[0]; start.water[1] = 0; start.water[2] = 0; start.step = 0; // printf("%d %d %d %d\n", start.water[0], start.water[1], start.water[2], start.step); Q.push(start); vis[start.water[0]][start.water[1]][start.water[2]] = 1; while(!Q.empty()) { p = Q.front(); //printf("%d %d %d %d\n", p.water[0], p.water[1], p.water[2], p.step); Q.pop(); if(OK(p) == 1) { return p.step; } int i, j; for(i=0; i<3; i++) { for(j=1; j<3; j++) { int k = (i+j)%3; if(p.water[i] != 0 && p.water[k] < cup[k]) //倒水分成两种情况,足够倒满和不足够倒满 { q = p; int need = cup[k] - p.water[k]; if(q.water[i] >= need) { q.water[k] += need; q.water[i] -= need; } else { q.water[k] += p.water[i]; q.water[i] = 0; } q.step = p.step + 1; if(vis[q.water[0]][q.water[1]][q.water[2]] == 0) { vis[q.water[0]][q.water[1]][q.water[2]] = 1; Q.push(q); } } } } } return -1; } int main() { int n; scanf("%d", &n); while(n--) { int i; for(i=0; i<3; i++) { scanf("%d", &cup[i]); } for(i=0; i<3; i++) { scanf("%d", &end_water[i]); } printf("%d\n", bfs()); } return 0; }
-
贴最优代码
-
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<bitset> using namespace std; #define CLR(arr,val) memset(arr,val,sizeof(arr)) bitset<1000000> Hash; const int MAX_STEP=100000; int WQ[MAX_STEP][4],Goal[3],Cap[3],goalval; int head=0,tail=0; void movw(int numfrom,int numto,int other) { int total=WQ[head][numfrom]+WQ[head][numto]; WQ[tail][other]=WQ[head][other]; WQ[tail][3]=WQ[head][3]+1; if(total>Cap[numto]) { WQ[tail][numfrom]=total-Cap[numto]; WQ[tail][numto]=Cap[numto]; } else { WQ[tail][numfrom]=0; WQ[tail][numto]=total; } int hashval=WQ[tail][0]*10000+WQ[tail][1]*100+WQ[tail][2]; if(hashval==goalval) throw WQ[head][3]+1; if(WQ[head][numfrom]!=0 && !Hash[hashval]) { Hash[hashval]=true; if(++tail==MAX_STEP) tail=0; } } int main() { int t; scanf("%d",&t); while(t--) { Hash.reset(); scanf("%d%d%d%d%d%d",&Cap[0],&Cap[1],&Cap[2],&Goal[0],&Goal[1],&Goal[2]); head=0,tail=0,goalval=Goal[0]*10000+Goal[1]*100+Goal[2]; if(Goal[1]==0 && Goal[2]==0 && Goal[0]==Cap[0]) {puts("0");continue;} WQ[tail][0]=Cap[0];WQ[tail][1]=0;WQ[tail][2]=0;WQ[tail][3]=0; ++tail; try{ while(head!=tail) { movw(0,1,2);movw(1,2,0);movw(0,2,1);movw(1,0,2);movw(2,1,0);movw(2,0,1); if(++head==MAX_STEP) head=0; } puts("-1"); }catch(int step) { printf("%d\n",step); } } }
-
-
第一行一个整数N(0<N<50)表示N组测试数据