1. 程式人生 > >NYOJ #21 三個水杯(bfs)

NYOJ #21 三個水杯(bfs)

描述

給出三個水杯,大小不一,並且只有最大的水杯的水是裝滿的,其餘兩個為空杯子。三個水杯之間相互倒水,並且水杯沒有標識,只能根據給出的水杯體積來計算。現在要求你寫出一個程式,使其輸出使初始狀態到達目標狀態的最少次數。

輸入

第一行一個整數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

解題思路:bfs求最少的倒水次數,每次都有6種倒水可能,標記一下三個水杯的容量狀態,用佇列來模擬倒水過程,如果出現某個過程達到最終的倒水狀態,則直接返回其倒水次數;否則直到隊空,返回-1,說明不能到達最終的容量狀態。詳解看程式碼。

AC程式碼:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int t,Vmax[3],Est[3],Cur[3];
 4 bool vis[105][105][105];
 5 struct
node{int a,b,c,step;}cur,tmp; 6 queue<node> que; 7 int bfs(int x){ 8 while(!que.empty())que.pop(); 9 cur.a=x,cur.b=cur.c=cur.step=0; 10 vis[cur.a][cur.b][cur.c]=true; 11 que.push(cur); 12 while(!que.empty()){ 13 cur=que.front();que.pop(); 14 if(cur.a==Est[0
]&&cur.b==Est[1]&&cur.c==Est[2])return cur.step;//到達最終的狀態 15 for(int i=0;i<3;++i){ 16 for(int j=0;j<3;++j){//6種倒水可能 17 tmp=cur;Cur[0]=tmp.a,Cur[1]=tmp.b,Cur[2]=tmp.c;//每次重新賦值 18 if(i!=j&&Cur[i]>0&&Cur[j]<Vmax[j]){//i-->j,如果第i個桶的水量大於0,並且第j個桶的水量不超過其最大容量 19 int gg=min(Cur[i],Vmax[j]-Cur[j]);//如果第j個桶剩餘容量小於第i個桶裡的水量,那麼只能倒Vmax[j]-Cur[j];反之,將第i個桶的水量全部倒給第j個桶 20 Cur[i]-=gg,Cur[j]+=gg;// i--->j 21 if(!vis[Cur[0]][Cur[1]][Cur[2]]){//狀態未出現過 22 vis[Cur[0]][Cur[1]][Cur[2]]=true; 23 tmp.a=Cur[0],tmp.b=Cur[1],tmp.c=Cur[2];//重新賦值 24 tmp.step++; 25 que.push(tmp); 26 } 27 } 28 } 29 } 30 } 31 return -1;//不滿足條件則返回-1 32 } 33 int main(){ 34 while(cin>>t){ 35 while(t--){ 36 for(int i=0;i<3;++i)cin>>Vmax[i]; 37 for(int i=0;i<3;++i)cin>>Est[i]; 38 memset(vis,false,sizeof(vis)); 39 cout<<bfs(Vmax[0])<<endl; 40 } 41 } 42 return 0; 43 }