NYOJ—三个水杯【搜索|广搜|BFS】

4 篇文章 0 订阅
3 篇文章 0 订阅

三个水杯

时间限制:1000 ms | 内存限制:65535 KB
难度:4

描述

给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子。三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算。现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数。

输入

第一行一个整数N(0

输出

每行输出相应测试数据最少的倒水次数。如果达不到目标状态输出-1

样例输入

2
6 3 1
4 1 1
9 3 2
7 1 1

样例输出

3
-1

思路

既然是找最少的次数,那就使用广搜,把当前状态每一个可以互相倒水且不与之前重复的状态放入队列中,每次取对首元素时判断是否为最终状态,不是的话继续放。如果取到队空则说明达不到目标返回-1

代码如下

#include <iostream>
#include <stdio.h>
#include <map>
#include <queue>
using namespace std;
int m[3];
int z_m[3];
struct zhuang_tai{
    int L[3];
    int sum;
    bool operator < (const zhuang_tai &a)const      ///重载<运算符用于结构体排序
    {
            if(a.L[0]==L[0])
                if(a.L[1]==L[1])
                    if(a.L[2]==L[2]);
                    else
                        return a.L[2]<L[2];
                else
                    return a.L[1]<L[1];
            return a.L[0]<L[0];
    }
}ans,k;
queue<zhuang_tai>q;
map<zhuang_tai,int>mp;

int pan(zhuang_tai a)        ///判断是否与目标状态相同
{
    if(a.L[0]==z_m[0]&&a.L[2]==z_m[2]&&a.L[1]==z_m[1])
        return 1;
    return 0;
}
void swp(int a ,int b,int c)
{
    zhuang_tai ans1;
    if(ans.L[a]<(m[b]-ans.L[b]))///如果第一个杯子水小于要倒的杯子剩余容量就全部倒到第二个杯子
    {
        ans1.L[a]=0;
        ans1.L[b]=ans.L[b]+ans.L[a];
    }
    else                        ///否则把第二个杯子倒满
    {
        ans1.L[a]=ans.L[a]-(m[b]-ans.L[b]);
        ans1.L[b]=m[b];
    }
    ans1.L[c]=ans.L[c];
    ans1.sum=0;
    if(!mp.count(ans1))         ///判断三种杯子状态是否出现过,如果没有出现过就入队
    {
        mp[ans1]++;
        ans1.sum=ans.sum+1;
        q.push(ans1);
    }
}
int main()
{

    int w;cin>>w;
    while(w--)
    {
        while(!q.empty())
            q.pop();
        mp.clear();
        cin>>m[0]>>m[1]>>m[2];
        cin>>z_m[0]>>z_m[1]>>z_m[2];
        ans.L[0]=m[0];
        ans.L[1]=0;
        ans.L[2]=0;
        ans.sum=0;
        q.push(ans);
        int summ=0;
        while(!q.empty())
        {
            ans=q.front();
            summ++;
            q.pop();
            if(pan(ans))  ///判断是否与目标状态相同
            {
                cout<<ans.sum<<endl;
                 goto go;      ///跳过输出-1的情况
            }
            swp(0,1,2);    ///六种相互倒的状态
            swp(0,2,1);
            swp(1,0,2);
            swp(1,2,0);
            swp(2,1,0);
            swp(2,0,1);
        }
        cout<<-1<<endl;
        go:;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值