1117 - 三个水杯
时间限制:1秒 内存限制:128兆
题目描述
给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子。三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算。现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数。
输入
第一行一个整数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
三个水杯问题其实就是对水杯里面的水进行互相倒的过程,我们可以用三维数组来标记每一次倒水后的状态,如果在倒水后发现之前出现过这个状态,那么就说明此时已经重复操作了,return出去就好
下面是dfs暴力代码
#include<stdio.h>
#include<string.h>
int zt[105][105][105];
int sa,sb,sc;
int flag,step;
int ea,eb,ec;
void dfs(int a,int b, int c,int num)
{
if(flag==1&&num>step)//如果所需次数大于之前成功状态时的次数,返回上一步操作
return ;
if(a==ea&&b==eb&&c==ec)//满足最终状态条件,进行判断
{
if(step==0)//第一次的成功状态
step=num;
else//不止一次能够达到成功状态
{
if(step>num)
step=num;
}
flag=1;
return ;
}
for(int i=1;i<=6;i++)
{
if(i==1)//a向b倒水
{
if(a>sb-b&&b!=sb)//a水杯向b水杯倒水,能将b水杯倒满的情况
{
int x=b;
a=a-sb+x;
b=sb;
if(zt[a][b][c]==1)
{
b=x;
a=a-x+sb;
continue ;
}
zt[a][b][c]=1;
dfs(a,b,c,num+1);
zt[a][b][c]=0;
b=x;
a=a-x+sb;
}
else//a向b倒水,把a水杯倒空的情况
{
if(a!=0)
{
int x=a;
b=b+x;
a=0;
if(b<=sb)
{
if(zt[a][b][c]==1)
{
a=x;
b=b-x;
continue ;
}
zt[a][b][c]=1;
dfs(a,b,c,num+1);
zt[a][b][c]=0;
}
a=x;
b=b-x;
}
}
}
if(i==2)//a向c倒水
{
if(a>sc-c&&c!=sc) //将c倒满
{
int x=c;
a=a-sc+c;
c=sc;
if(zt[a][b][c]==1)
{
a=a-x+sc;
c=x;
continue ;
}
zt[a][b][c]=1;
dfs(a,b,c,num+1);
zt[a][b][c]=0;
a=a-x+sc;
c=x;
}
else//将a倒空
{
if(a!=0)
{
int x=a;
c=c+a;
a=0;
if(c<=sc)
{
if(zt[a][b][c]==1)
{
a=x;
c=c-x;
continue ;
}
zt[a][b][c]=1;
dfs(a,b,c,num+1);
zt[a][b][c]=0;
}
a=x;
c=c-x;
}
}
}
if(i==3)//b向a倒水
{
if(b<sa-a)//将b倒空
{
if(b!=0)
{
int x=b;
a=a+b;
b=0;
if(a<=sa)
{
if(zt[a][b][c]==1)
{
b=x;
a=a-x;
continue ;
}
zt[a][b][c]=1;
dfs(a,b,c,num+1);
zt[a][b][c]=0;
}
b=x;
a=a-x;
}
}
else//将a倒满
{
int x=a;
b=b-sa+a;
a=sa;
if(zt[a][b][c]==1)
{
a=x;
b=b-x+sa;
continue ;
}
zt[a][b][c]=1;
dfs(a,b,c,num+1);
zt[a][b][c]=0;
a=x;
b=b-x+sa;
}
}
if(i==4)//b向c倒水
{
if(b>sc-c&&c!=sc)//将c倒满
{
int x=c;
b=b-sc+c;
c=sc;
if(zt[a][b][c]==1)
{
b=b-x+sc;
c=x;
continue ;
}
zt[a][b][c]=1;
dfs(a,b,c,num+1);
zt[a][b][c]=0;
b=b-x+sc;
c=x;
}
else//将b倒空
{
if(b!=0)
{
int x=b;
c=c+b;
b=0;
if(c<=sc)
{
if(zt[a][b][c]==1)
{
b=x;
c=c-x;
continue ;
}
zt[a][b][c]=1;
dfs(a,b,c,num+1);
zt[a][b][c]=0;
}
b=x;
c=c-x;
}
}
}
if(i==5)//c向a倒水
{
if(c>sa-a&&a!=sa)//将a倒满
{
int x=a;
c=c-sa+a;
a=sa;
if(zt[a][b][c]==1)
{
c=c-x+sa;
a=x;
continue ;
}
zt[a][b][c]=1;
dfs(a,b,c,num+1);
zt[a][b][c]=0;
c=c-x+sa;
a=x;
}
else//将c倒空
{
if(c!=0)
{
int x=c;
a=a+c;
c=0;
if(zt[a][b][c]==1)
{
a=a-x;
c=x;
continue ;
}
zt[a][b][c]=1;
dfs(a,b,c,num+1);
zt[a][b][c]=0;
a=a-x;
c=x;
}
}
}
if(i==6)//c向b倒水
{
if(c>sb-b&&b!=sb)//将b倒满
{
int x=b;
c=c-sb+b;
b=sb;
if(zt[a][b][c]==1)
{
b=x;
c=c-x+sb;
continue ;
}
zt[a][b][c]=1;
dfs(a,b,c,num+1);
zt[a][b][c]=0;
b=x;
c=c-x+sb;
}
else//将c倒空
{
int x=c;
b=b+c;
c=0;
if(b<=sb)
{
if(zt[a][b][c]==1)
{
c=x;
b=b-x;
continue ;
}
zt[a][b][c]=1;
dfs(a,b,c,num+1);
zt[a][b][c]=0;
}
c=x;
b=b-x;
}
}
}
}
int main()
{
int n;
scanf("%d",&n);
while(n--)
{
scanf("%d %d %d",&sa,&sb,&sc);
scanf("%d %d %d",&ea,&eb,&ec);
if(sa==ea&&eb==0&&ec==0)
printf("0\n");
else
{
zt[sa][0][0]=1;
dfs(sa,0,0,0);
if(step!=0)
printf("%d\n",step);
if(step==0)
printf("-1\n");
}
step=0;
flag=0;
memset(zt,0,sizeof(zt));
}
}
以下为向xzl借鉴的bfs代码,思路是一样的,代码中不再做说明
#include<iostream>
#include<queue>
#include<string.h>
using namespace std;
int v1,v2,v3;
int e1,e2,e3;
struct Node
{
int x,y,z,step;
Node(){}
Node(int xx,int yy,int zz,int ss) : x(xx) , y(yy) , z(zz) ,step(ss) {}
};
int book[110][110][110];
int bfs(int x,int y,int z,int ss)
{
memset(book,0,sizeof(book));
queue<Node> Q;
Q.push(Node(x,y,z,ss));
book[x][y][z] = 1 ;
while(!Q.empty())
{
Node u = Q.front();
Q.pop();
if(u.x==e1&&u.y==e2&&u.z==e3)
{
return u.step ;
}
for(int i = 0 ; i < 6 ; i++)
{
Node s = u ;
if(i == 0 ) // a - b
{
int minn = min(s.x , v2 - s.y);
s.x-=minn;
s.y+=minn;
}
if(i == 1 ) // a - c
{
int minn = min(s.x , v3 - s.z);
s.x-=minn;
s.z+=minn;
}
if(i == 2 ) // b - a
{
int minn = min(s.y , v1 - s.x);
s.x+=minn;
s.y-=minn;
}
if(i == 3 ) // b - c
{
int minn = min(s.y , v3 - s.z);
s.z+=minn;
s.y-=minn;
}
if(i == 4 ) // c - b
{
int minn = min(s.z , v2 - s.y);
s.z-=minn;
s.y+=minn;
}
if(i == 5 ) // c - a
{
int minn = min(s.z , v1 - s.x);
s.x+=minn;
s.z-=minn;
}
int sss = u.step + 1 ;
if(book[s.x][s.y][s.z] == 0)
{
Q.push(Node(s.x,s.y,s.z,sss));
book[s.x][s.y][s.z] = 1 ;
}
}
}
return -1;
}
int main()
{
int n;
scanf("%d",&n);
while(n--)
{
scanf("%d %d %d",&v1,&v2,&v3);
scanf("%d %d %d",&e1,&e2,&e3);
int ans = bfs(v1 , 0, 0 ,0);
printf("%d\n",ans);
}
}