三个水杯
时间限制: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 <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
int sv[4],dv[4]; //sv保存开始的状态,dv保存需要的最终状态
int book[100][100][100];
struct cup{
int v[4]; //v保存倒水过程中各水杯的状态
int times; //times保存倒水的次数
};
void move(cup &a,int x1,int x2) //从v[x1]向v[x2]倒水
{
if(a.v[x1]+a.v[x2]<=sv[x2])
{
a.v[x2]=a.v[x2]+a.v[x1];
a.v[x1]=0;
}
else
{
a.v[x1]=a.v[x1]-(sv[x2]-a.v[x2]);
a.v[x2]=sv[x2];
}
}
int bfs(cup x)
{
queue<cup>all;
all.push(x); //x为水杯的起始状态
cup y;
while(!all.empty())
{
x=all.front();
all.pop();
if(x.v[1]==dv[1] && x.v[2]==dv[2] && x.v[3]==dv[3]) //如果达到最终需要的状态,返回
return x.times;
for(int i=1;i<4;i++)
for(int j=1;j<4;j++)
{
if(i==j || x.v[i]==0 || x.v[j]==sv[j]) //若v[i]中没水或v[j]中水满,继续下一循环
continue;
y=x;
move(y,i,j); //从v[i]中向v[j]中倒水
y.times++;
if(book[y.v[1]][y.v[2]][y.v[3]]==0)
{
book[y.v[1]][y.v[2]][y.v[3]]=1;
all.push(y);
}
}
}
return -1; //如果不能达到最终状态,返回-1
}
int main()
{
int n;
scanf("%d",&n);
while(n--)
{
memset(book,0,sizeof(book));
for(int i=1;i<4;i++)
scanf("%d",&sv[i]);
for(int i=1;i<4;i++)
scanf("%d",&dv[i]);
cup x; //定义x,x中水杯为起始状态,倒水次数times=0
x.v[1]=sv[1];
x.v[2]=x.v[3]=0;
x.times=0;
book[x.v[1]][x.v[2]][x.v[3]]=1;
printf("%d\n",bfs(x));
}
return 0;
}