NYOJ-21 三个水杯

三水杯问题求解
本文探讨了经典的三水杯问题,通过BFS算法找出从初始状态到目标状态的最少倒水次数。提供了两种实现方案,包括详细的伪代码,帮助读者理解如何高效地解决这一问题。

三个水杯

时间限制: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


BFS


01.#include <iostream>
02.#include <queue>
03.#include <string.h>
04.using namespace std;
05. 
06.struct node
07.{
08.int sta[3];
09.int step;
10.};
11. 
12.int visit[100][100][100];
13.int v[3],e[3];
14.queue<node> qu;
15. 
16.int check(node x)
17.{
18.if(x.sta[0]==e[0]&&x.sta[1]==e[1]&&x.sta[2]==e[2])
19.return 1;
20.else
21.return 0;
22.}
23. 
24.int bfs(int x,int y,int z)
25.{
26.node t;
27.t.sta[0]=x;
28.t.sta[1]=y;
29.t.sta[2]=z;
30.t.step=0;
31.qu.push(t);
32.while(!qu.empty())
33.{
34.node t1;
35.t1=qu.front();
36.qu.pop();
37.for(int i=0;i<3;i++)
38.for(int j=0;j<3;j++)
39.{
40.if(i!=j)
41.{
42.if(t1.sta[i]&&t1.sta[j]!=v[j])
43.{
44.node t2;
45.t2.sta[0]=t1.sta[0];
46.t2.sta[1]=t1.sta[1];
47.t2.sta[2]=t1.sta[2];
48.t2.step=t1.step+1;
49.if(t1.sta[i]>=v[j]-t1.sta[j])
50.{
51.t2.sta[i]=t1.sta[i]-(v[j]-t1.sta[j]);
52.t2.sta[j]=v[j];
53.}
54.else
55.{
56.t2.sta[i]=0;
57.t2.sta[j]=t1.sta[i]+t1.sta[j];
58.}
59.if(!visit[t2.sta[0]][t2.sta[1]][t2.sta[2]])
60.{
61.if(check(t2))
62.return t2.step;
63.visit[t2.sta[0]][t2.sta[1]][t2.sta[2]]=1;
64.qu.push(t2);
65.}                      
66.}
67.}
68.}
69.}
70.return -1;
71.}
72.int main()
73.{
74.int n;
75.cin>>n;
76.while(n--)
77.{
78.memset(visit,0,sizeof(visit));
79.cin>>v[0]>>v[1]>>v[2];
80.cin>>e[0]>>e[1]>>e[2];
81.if(e[0]==v[0]&&e[1]==0&&e[2]==0)
82.{
83.cout<<"0"<<endl;
84.continue;
85.}
86.visit[v[0]][0][0]=1;
87.cout<<bfs(v[0],0,0)<<endl;
88.}
89.return 0;
90.}
   

再贴一个最优的


01.#include<iostream>
02.#include<cstdio>
03.#include<cstring>
04.#include<algorithm>
05.#include<bitset>
06.using namespace std;
07.#define CLR(arr,val) memset(arr,val,sizeof(arr))
08.bitset<1000000> Hash;
09.const int MAX_STEP=100000;
10.int WQ[MAX_STEP][4],Goal[3],Cap[3],goalval;
11.int head=0,tail=0;
12.void movw(int numfrom,int numto,int other)
13.{
14.int total=WQ[head][numfrom]+WQ[head][numto];
15.WQ[tail][other]=WQ[head][other];
16.WQ[tail][3]=WQ[head][3]+1;
17.if(total>Cap[numto])
18.{
19.WQ[tail][numfrom]=total-Cap[numto];
20.WQ[tail][numto]=Cap[numto];
21.}
22.else
23.{
24.WQ[tail][numfrom]=0;
25.WQ[tail][numto]=total;
26.}
27.int hashval=WQ[tail][0]*10000+WQ[tail][1]*100+WQ[tail][2];
28.if(hashval==goalval) throw WQ[head][3]+1;
29.if(WQ[head][numfrom]!=0 && !Hash[hashval])
30.{
31.Hash[hashval]=true;
32.if(++tail==MAX_STEP) tail=0;
33.}
34.}
35.int main()
36.{
37.int t;
38.scanf("%d",&t);
39.while(t--)
40.{
41.Hash.reset();
42.scanf("%d%d%d%d%d%d",&Cap[0],&Cap[1],&Cap[2],&Goal[0],&Goal[1],&Goal[2]);
43.head=0,tail=0,goalval=Goal[0]*10000+Goal[1]*100+Goal[2];
44.if(Goal[1]==0 && Goal[2]==0 && Goal[0]==Cap[0]) {puts("0");continue;}
45.WQ[tail][0]=Cap[0];WQ[tail][1]=0;WQ[tail][2]=0;WQ[tail][3]=0;
46.++tail;
47.try{
48.while(head!=tail)
49.{
50.movw(0,1,2);movw(1,2,0);movw(0,2,1);movw(1,0,2);movw(2,1,0);movw(2,0,1);
51.if(++head==MAX_STEP) head=0;
52.}
53.puts("-1");
54.}catch(int step)
55.{
56.printf("%d\n",step);
57.}
58.}
59.}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值