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

这是我写过最长的模拟题,没有之一

代码

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<queue>
using namespace std;
//三个水杯广搜一遍
const int maxn=101;
bool visited[maxn][maxn][maxn];//出现过的状态标记为1
int V1,V2,V3;//三个水杯的体积
int E1,E2,E3;//目标状态
struct node
{
    int A1,A2,A3;
    int steap;
};
void BFS(int steap,int A1,int A2,int A3)//传入倒水次数,当前状态
{
    queue<node>q;
    node star;
    star.A1=A1;
    star.A2=A2;
    star.A3=A3;
    star.steap=steap;
    q.push(star);
    memset(visited,false,sizeof(visited));
    visited[star.A1][star.A2][star.A3]=1;//初始状态标记为已出现
    while(!q.empty())
    {
        star=q.front();
        q.pop();
        //接着就是6种搜索方向
        //当搜索到的状态满足目标状态就输出,出现重复状态不允许入队
        node end;
        if(star.A1>0)//A1有水
        {
            if(star.A2<V2)//A2没满就可以从A1倒给A2
            {
                if(star.A1<=V2-star.A2)//可以把A1全部倒进A2
                {
                    end.A1=0;
                    end.A2=star.A2+star.A1;
                    end.A3=star.A3;
                    end.steap=star.steap+1;
                    if(end.A1==E1&&end.A2==E2&&end.A3==E3)
                    {
                        printf("%d\n",end.steap);
                        return;
                    }
                    if(visited[end.A1][end.A2][end.A3]==0)
                    {
                        q.push(end);
                        visited[end.A1][end.A2][end.A3]=1;
                    }
                }
                else//A1倒一部分进A2,把A2充满
                {
                    end.A1=star.A1-(V2-star.A2);
                    end.A2=V2;
                    end.A3=star.A3;
                    end.steap=star.steap+1;
                    if(end.A1==E1&&end.A2==E2&&end.A3==E3)
                    {
                        printf("%d\n",end.steap);
                        return;
                    }
                    if(visited[end.A1][end.A2][end.A3]==0)
                    {
                        q.push(end);
                        visited[end.A1][end.A2][end.A3]=1;
                    }
                }
            }
            if(star.A3<V2)//A3没满就可以从A1倒给A3
            {
                if(V3-star.A3>=star.A1)//如果A1可以全部倒给A3
                {
                    end.A1=0;
                    end.A2=star.A2;
                    end.A3=star.A1+star.A3;
                    end.steap=star.steap+1;
                    if(end.A1==E1&&end.A2==E2&&end.A3==E3)
                    {
                        printf("%d\n",end.steap);
                        return;
                    }
                    if(visited[end.A1][end.A2][end.A3]==0)
                    {
                        q.push(end);
                        visited[end.A1][end.A2][end.A3]=1;
                    }
                }
                else//A1倒一部分给A3把A3充满
                {
                    end.A1=star.A1-(V3-star.A3);
                    end.A2=star.A2;
                    end.A3=V3;
                    end.steap=star.steap+1;
                    if(end.A1==E1&&end.A2==E2&&end.A3==E3)
                    {
                        printf("%d\n",end.steap);
                        return;
                    }
                    if(visited[end.A1][end.A2][end.A3]==0)
                    {
                        q.push(end);
                        visited[end.A1][end.A2][end.A3]=1;
                    }
                }
            }
        }
        if(star.A2>0)//如果A2有水
        {
            if(star.A1<V1)//A1没满,可以从A2倒向A1
            {
                if(V1-star.A1>=star.A2)//把A2全部倒进A1
                {
                    end.A1=star.A1+star.A2;
                    end.A2=0;
                    end.A3=star.A3;
                    end.steap=star.steap+1;
                    if(end.A1==E1&&end.A2==E2&&end.A3==E3)
                    {
                        printf("%d\n",end.steap);
                        return;
                    }
                    if(visited[end.A1][end.A2][end.A3]==0)
                    {
                        q.push(end);
                        visited[end.A1][end.A2][end.A3]=1;
                    }
                }
                else//A2一部分倒进A1使A1充满
                {
                    end.A1=V1;
                    end.A2=star.A2-(V1-star.A1);
                    end.A3=star.A3;
                    end.steap=star.steap;
                    if(end.A1==E1&&end.A2==E2&&end.A3==E3)
                    {
                        printf("%d\n",end.steap);
                        return;
                    }
                    if(visited[end.A1][end.A2][end.A3]==0)
                    {
                        q.push(end);
                        visited[end.A1][end.A2][end.A3]=1;
                    }
                }
            }
            if(star.A3<V3)//如果A3没满,可以从A2倒向A3
            {
                if(V3-star.A3>=star.A2)//把A2全部倒进A3
                {
                    end.A1=star.A1;
                    end.A2=0;
                    end.A3=star.A3+star.A2;
                    end.steap=star.steap+1;
                    if(end.A1==E1&&end.A2==E2&&end.A3==E3)
                    {
                        printf("%d\n",end.steap);
                        return;
                    }
                    if(visited[end.A1][end.A2][end.A3]==0)
                    {
                        q.push(end);
                        visited[end.A1][end.A2][end.A3]=1;
                    }
                }
                else//把A2部分倒进A3使A3充满
                {
                    end.A1=star.A1;
                    end.A2=star.A2-(V3-star.A3);
                    end.A3=V3;
                    end.steap=star.steap+1;
                    if(end.A1==E1&&end.A2==E2&&end.A3==E3)
                    {
                        printf("%d\n",end.steap);
                        return;
                    }
                    if(visited[end.A1][end.A2][end.A3]==0)
                    {
                        q.push(end);
                        visited[end.A1][end.A2][end.A3]=1;
                    }
                }
            }
        }
        if(star.A3>0)//如果A3有水
        {
            if(star.A1<V1)//A1没满,可以从A3倒向A1
            {
                if(V1-star.A1>=star.A3)//把A3全部倒进A1
                {
                    end.A1=star.A1+star.A3;
                    end.A2=star.A2;
                    end.A3=0;
                    end.steap=star.steap+1;
                    if(end.A1==E1&&end.A2==E2&&end.A3==E3)
                    {
                        printf("%d\n",end.steap);
                        return;
                    }
                    if(visited[end.A1][end.A2][end.A3]==0)
                    {
                        q.push(end);
                        visited[end.A1][end.A2][end.A3]=1;
                    }
                }
                else//A3部分倒进A1使A1充满
                {
                    end.A1=V1;
                    end.A2=star.A2;
                    end.A3=star.A3-(V1-star.A1);
                    end.steap=star.steap+1;
                    if(end.A1==E1&&end.A2==E2&&end.A3==E3)
                    {
                        printf("%d\n",end.steap);
                        return;
                    }
                    if(visited[end.A1][end.A2][end.A3]==0)
                    {
                        q.push(end);
                        visited[end.A1][end.A2][end.A3]=1;
                    }
                }
            }
            if(star.A2<V2)//如果A2没满,可以从A3倒向A2
            {
                if(V2-star.A2>=star.A3)//把A3全部倒进A2
                {
                    end.A1=star.A1;
                    end.A2=star.A2+star.A3;
                    end.A3=0;
                    end.steap=star.steap+1;
                    if(end.A1==E1&&end.A2==E2&&end.A3==E3)
                    {
                        printf("%d\n",end.steap);
                        return;
                    }
                    if(visited[end.A1][end.A2][end.A3]==0)
                    {
                        q.push(end);
                        visited[end.A1][end.A2][end.A3]=1;
                    }
                }
                else//A3部分倒进A2使A2充满
                {
                    end.A1=star.A1;
                    end.A2=V2;
                    end.A3=star.A3-(V2-star.A2);
                    end.steap=star.steap+1;
                    if(end.A1==E1&&end.A2==E2&&end.A3==E3)
                    {
                        printf("%d\n",end.steap);
                        return;
                    }
                    if(visited[end.A1][end.A2][end.A3]==0)
                    {
                        q.push(end);
                        visited[end.A1][end.A2][end.A3]=1;
                    }
                }
            }
        }
    }
    printf("-1\n");
    return;
}
int main()
{
    int N;
    scanf("%d",&N);
    while(N--)
    {
        scanf("%d%d%d%d%d%d",&V1,&V2,&V3,&E1,&E2,&E3);
        if(E1+E2+E3>V1)//两种特判
        {
            printf("-1\n");
            continue;
        }
        if(E1==V1&&E2==0&&E3==0)
        {
            printf("0\n");
            continue;
        }
        BFS(0,V1,0,0);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值