三個水杯
- 描述
- 給出三個水杯,大小不一,並且只有最大的水杯的水是裝滿的,其餘兩個爲空杯子。三個水杯之間相互倒水,並且水杯沒有標識,只能根據給出的水杯體積來計算。現在要求你寫出一個程序,使其輸出使初始狀態到達目標狀態的最少次數。
- 輸入
- 第一行一個整數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); } } }
-