三個水杯
時間限制: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
-
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
queue<int>q;
int v[3], e[3];
int mark[100][100][100];//標記數組
void bfs();
int acount = 0;
int main()
{
int n;
cin>>n;
while(n--)
{
while(!q.empty())
{
q.pop();
}
acount = 0;
memset(mark, 0, sizeof(mark));
cin>>v[0]>>v[1]>>v[2];
cin>>e[0]>>e[1]>>e[2];
if(v[0] == e[0] && e[1] == 0 && e[3] == 0) //如果開始狀態與要求結束狀態相同則輸出0
cout<<"0"<<endl;
else if(v[0] == e[0] && (e[0] > 0 || e[2] > 0)) //如果要求狀態的第一個水杯是滿的且第二個水杯或第三個不是空的則說明水不夠用的
cout<<"-1"<<endl;
else
{
//把初始狀態壓入隊列中並將其標記
q.push(v[0]);
q.push(0);
q.push(0);
q.push(0);
mark[v[0]][0][0] = 1;
bfs();
}
}
return 0;
}
void bfs()
{
int i, j;
int flag[4] = {0}, a[4] = {0};
while(!q.empty())
{
memset(a, 0, sizeof(a));
//從隊列中提取元素
flag[0] = q.front(); q.pop();
flag[1] = q.front(); q.pop();
flag[2] = q.front(); q.pop();
flag[3] = q.front(); q.pop();//倒水的次數
for(i = 0; i < 3; i++)
for(j = 0; j < 3; j++)
{
//把flag[i]的水倒入flag[j]中
if(i == j)
continue;
if(flag[i] == 0 || flag[j] == v[j])//如果flag[i]是空的或者flag[j]是滿的,則選擇下一種狀態.
continue;
a[0] = flag[0];
a[1] = flag[1];
a[2] = flag[2];
if(flag[i] < v[j] - flag[j])//flag[i]的水少於flag[j]的水 則把flag[i]的水全部倒入flag[j]中
{
a[j] = flag[j] + flag[i];
a[i] = 0;
}
else //flag[i]的水多於flag[j]的水 則把flag[j]倒滿
{
a[i] = flag[i] - (v[j] - flag[j]);
a[j] = v[j];
}
a[3] = flag[3] + 1;//倒水的次數加一
if(!mark[a[0]][a[1]][a[2]])
{
if(a[0] == e[0] && a[1] == e[1] && a[2] == e[2])//如果與要求狀態相同則輸出次數
{
cout<<a[3]<<endl;
return ;
}
//將現在的狀態標記並將其壓入隊列中
mark[a[0]][a[1]][a[2]] = 1;
q.push(a[0]);
q.push(a[1]);
q.push(a[2]);
q.push(a[3]);
}
}
}
//如果隊列空了並且沒有到達要求狀態則輸出-1
cout<<"-1"<<endl;
return ;
}