三个水杯 21 (bfs 转化) 好题

来源:互联网 发布:淘宝优惠券app哪个好 编辑:程序博客网 时间:2024/04/29 21:49

三个水杯

时间限制:1000 ms  |           内存限制:65535 KB
难度:4
描述
给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子。三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算。现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数。
输入
第一行一个整数N(0<N<50)表示N组测试数据
接下来每组测试数据有两行,第一行给出三个整数V1 V2 V3 (V1>V2>V3 V1<100 V3>0)表示三个水杯的体积。
第二行给出三个整数E1 E2 E3 (体积小于等于相应水杯体积)表示我们需要的最终状态
输出
每行输出相应测试数据最少的倒水次数。如果达不到目标状态输出-1
样例输入
26 3 14 1 19 3 27 1 1
样例输出
3-1
#include<stdio.h>#include<string.h>#include<queue>#include<algorithm>using namespace std;int a[3],b[3],c[1010][1010];struct zz{int d[3];int l;}f1,f2;void bfs(){memset(c,0,sizeof(c));queue<zz>q;f1.d[0]=a[0];f1.d[1]=0;f1.d[2]=0;f1.l=0;q.push(f1);c[0][0]=0;while(!q.empty()){f1=q.front();q.pop();for(int i=0;i<3;i++)//每次倒水都是在两个水杯间进行,所以用两重for循环,将所有情况遍历。 {for(int j=0;j<3;j++){f2=f1;if(i!=j)//不能是同一个水杯 {if(f2.d[0]==b[0]&&f2.d[1]==b[1]&&f2.d[2]==b[2])//如果三个水杯中的水达到目标 {printf("%d\n",f2.l);//就输出他们之间倒水的次数 return ;}f2.l=f1.l+1;//否则,倒水次数加1.//下面来判断将两个水杯中的水倒到其中一个中,两水杯中的水是否会超出这个水杯的容量。 if(f2.d[i]+f2.d[j]<a[j]) //若不超过,更新这两个水杯中的水。 {f2.d[j]=f2.d[i]+f2.d[j];//j水杯中的水更新为这两个水杯中的水的和。 f2.d[i]=0;//i中的水更新为0. }else//若两水杯中的水超过这一水杯的容量,那么这个水杯会被装满,其余的水还在另一个水杯中 {f2.d[i]=f2.d[i]+f2.d[j]-a[j];//i水杯的水更新为装满j水杯后剩余的水 f2.d[j]=a[j];//将j中的水更新为j水杯的容量。 }//因为有三个杯子,而且水的总量已知,那么只需要确定1,2的状态是否到达过。 if(c[f2.d[1]][f2.d[2]]==0)//如果以前没出现过这种情况,证明没有重复,也表示操作步数最小 {if(f2.d[0]==b[0]&&f2.d[1]==b[1]&&f2.d[2]==b[2])//如果打到目标水量 {printf("%d\n",f2.l);//输出步数 return ;}q.push(f2);//否则继续找 c[f2.d[1]][f2.d[2]]=1;//并将这种倒水结果标记为1,表示已经出现过,以后再出现就不是最小步数了 }}}}}printf("-1\n");}int main(){int n;scanf("%d",&n);while(n--){scanf("%d%d%d",&a[0],&a[1],&a[2]);scanf("%d%d%d",&b[0],&b[1],&b[2]);bfs();}return 0;}

0 0
原创粉丝点击