三个水杯
时间限制:
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
-
简单的宽度优先搜索,三个水杯之间的相互倒水如下图6种情况:
对于每一次倒水都会引起三个水杯水量状态的改变,这样就可以得到如下的一个解空间树:
#include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; int cupCapacity[4]; int targetState[4]; bool visit[100][100][100]; struct node{ int state[3]; int step; }; bool AchieveTargetState(node current){ for(int i=0;i<3;i++){ if(current.state[i]!=targetState[i]){ return false; } } return true; } void PourWater(int destination,int source,node &cup){ int waterYield=cupCapacity[destination]-cup.state[destination]; if(cup.state[source]>=waterYield){ cup.state[destination]+=waterYield; cup.state[source]-=waterYield; } else{ cup.state[destination]+=cup.state[source]; cup.state[source]=0; } } int bfs(){ node init; queue<node>que; memset(visit,false,sizeof(visit)); init.state[0]=cupCapacity[0]; init.state[1]=init.state[2]=0; init.step=0; que.push(init); visit[init.state[0]][0][0]=true; while(!que.empty()){ node top=que.front(); que.pop(); if(AchieveTargetState(top)){ return top.step; } for(int i=0;i<3;i++){ for(int j=1;j<3;j++){ int k=(i+j)%3; if(top.state[i]&&top.state[k]<cupCapacity[k]){ node tmp=top; PourWater(k,i,tmp); tmp.step=top.step+1; if(!visit[tmp.state[0]][tmp.state[1]][tmp.state[2]]){ visit[tmp.state[0]][tmp.state[1]][tmp.state[2]]=true; que.push(tmp); } } } } } return -1; } int main(){ int n; scanf("%d",&n); while(n--){ scanf("%d%d%d",&cupCapacity[0],&cupCapacity[1],&cupCapacity[2]); scanf("%d%d%d",&targetState[0],&targetState[1],&targetState[2]); int res=bfs(); printf("%d\n",res); } return 0; }