NYOJ 21 三个水杯

描述
给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子。三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算。现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数。
输入
第一行一个整数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 <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
struct node
{
    int a,b,c,step;//a,b,c 表示水杯中水的体积 为变量 step为变量,记录倒水的次数 
};


int v1,v2,v3,v11,v22,v33;
bool vis[101][101][101];  //标记情况有没有出现 三维数组 
void init()
{
    scanf("%d%d%d%d%d%d",&v1,&v2,&v3,&v11,&v22,&v33);//输入水杯的容量和要达到的状态 
}
    void bfs()
{
        bool flag=false;
        memset(vis,false,sizeof(vis));
        queue<node> que;  //建立一个队列 
        que.push(node{v1,0,0,0});  //初始化队列的状态 即第一个杯子(最大的杯子)是装满的 
        node n;//建立了一个结构体变量 
        int t;
        while(!que.empty())//如果  que.empty() 等于0   que.empty 队列是否为空的判断条件  此处的意思为 如果队列不是空队列 
   {
            n=que.front(); //n等于队列的对头元素 
   que.pop();//队首元素出队
            if(n.a==v11 && n.b==v22 && n.c==v33)//判断水杯中的水是否是想达到的状态 
   {
                flag=true; 
   break;
            }
            if(vis[n.a][n.b][n.c]) continue;//如果 vis[n.a][n.b][n.c] ==0  跳过 不予考虑 
            vis[n.a][n.b][n.c]=true;


            t=(n.a>=v2-n.b)? v2-n.b:n.a;  // t总是取两个之间较小的一个。 v2-n.b表示现状态与目标状态的差距 
            que.push(node{n.a-t,n.b+t,n.c,n.step+1});//倒水 从a中往b中倒水,将b装满。step+1 


            t=(n.a>=v3-n.c)? v3-n.c:n.a;
            que.push(node{n.a-t,n.b,n.c+t,n.step+1});


            t=(n.b>=v1-n.a)? v1-n.a:n.b;
            que.push(node{n.a+t,n.b-t,n.c,n.step+1});


            t=(n.b>=v3-n.c)? v3-n.c:n.b;
            que.push(node{n.a,n.b-t,n.c+t,n.step+1});


            t=(n.c>=v1-n.a)? v1-n.a:n.c;
            que.push(node{n.a+t,n.b,n.c-t,n.step+1});


            t=(n.c>=v2-n.b)? v2-n.b:n.c;
            que.push(node{n.a,n.b+t,n.c-t,n.step+1});//此六句构成一个循环 每次三个水杯内的水都会改变 直到到达目的状态为止 
        }
        if(flag) printf("%d\n",n.step);
        else printf("-1\n");
    }


int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
{
        init();
        bfs();
    }
    return 0;

}



下面的代码不是用队列

01.#include <iostream>
02.#include <cmath>
03.#include <algorithm>
04.#include <cstring>
05.#include <cstdio>
06.using namespace std;
07.int a[100];
08.int b[100];
09.int v[100];
10.int d[100][100][100];
11.int minn;
12.void fun(int k)
13.{
14.int i;
15.//for(i=0;i<3;i++) cout<<v[i]<<' '; cout<<' '<<k<<endl;
16.for(i=0;i<3;i++)
17.{
18.if(v[i]!=b[i]) break;
19.}
20.if(i==3)
21.{
22.if(minn>k)
23.minn=k;
24.return ;
25.//cout<<k<<endl;
26.}
27.for(i=0;i<3;i++)
28.{
29.for(int j=0;j<3;j++)
30.{
31.if(j==i) continue;
32.if(v[j]<a[j])
33.{
34.int p;
35.int c[100];
36.for(int t=0;t<3;t++)
37.c[t]=v[t];
38.if(v[i]-(a[j]-v[j])>=0)
39.{
40.v[i]=v[i]-(a[j]-v[j]);
41.p=a[j]-v[j];
42.}
43.else
44.{
45.p=v[i];
46.v[i]=0;
47.}
48.v[j]+=p;
49. 
50.if(d[v[0]][v[1]][v[2]]>k)
51.{
52.d[v[0]][v[1]][v[2]]=k;
53.fun(k+1);
54.}
55.for(int t=0;t<3;t++)
56.v[t]=c[t];
57.}
58.}
59.}
60.}
61.int main()
62.{
63.int t;
64.cin>>t;
65.while(t--)
66.{
67.memset(v,0,sizeof(v));
68.memset(d,1000000,sizeof(d));
69.int i;
70.minn=10000000;
71.for(i=0;i<3;i++)
72.cin>>a[i];
73.for(i=0;i<3;i++)
74.cin>>b[i];
75.v[0]=a[0];
76.fun(0);
77.if(minn!=10000000) cout<<minn<<endl;
78.else cout<<"-1"<<endl;
79.}
80.return 0;
81.}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值