HDU 1495 非常可乐

题目链接

Problem Description

大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为。因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要喝的和seeyou一样多。但seeyou的手中只有两个杯子,它们的容量分别是N 毫升和M 毫升 可乐的体积为S (S<101)毫升 (正好装满一瓶) ,它们三个之间可以相互倒可乐 (都是没有刻度的,且 S==N+M,101>S>0,N>0,M>0) 。聪明的ACMER你们说他们能平分吗?如果能请输出倒可乐的最少的次数,如果不能输出"NO"。

Input

三个整数 : S 可乐的体积 , N 和 M是两个杯子的容量,以"0 0 0"结束。

Output

如果能平分的话请输出最少要倒的次数,否则输出"NO"。

Sample Input

7 4 3
4 1 3
0 0 0

Sample Output

NO
3

具体思路
三个容器问是否能平分可乐,其实就是bfs的广搜题,每一个初始状态都有六种操作,即ntom,ntos,mton,mtos,stom,ston,每一个操作又有两种情况,一直是倒的杯子比被倒的剩余空间多,另一种就是少,就是一题大模拟bfs,代码有点长,一开始开个矩阵标记这三个容器状态值是否被使用过即可

#include<bits/stdc++.h>
using namespace std;
int bj[105][105][105];
int s,n,m,k;
queue<int>duis;
queue<int>duin;
queue<int>duim;
void bfs()
{
    while (!duis.empty()&&!duin.empty()&&!duim.empty())
    {
        int ss=duis.front();
        int nn=duin.front();
        int mm=duim.front();
       // printf("%d %d %d %d\n",ss,nn,mm,bj[ss][nn][mm]);
        if ((ss==k&&nn==k)||(ss==k&&mm==k)||(mm==k&&nn==k))
        {
            printf("%d\n",bj[ss][nn][mm]);
            return ;
        }
        if (bj[ss-(n-nn)][nn+(n-nn)][mm]==0&&ss-(n-nn)>=0&&nn+(n-nn)<=n)
        {
            bj[ss-(n-nn)][nn+(n-nn)][mm]=bj[ss][nn][mm]+1;
            //printf("%d\n", bj[ss-(n-nn)][nn+(n-nn)][mm]);
            duis.push(ss-(n-nn));
            duin.push(nn+(n-nn));
            duim.push(mm);
        }
        if (bj[ss-(m-mm)][nn][mm+(m-mm)]==0&&ss-(m-mm)>=0&&mm+(m-mm)<=m)
        {
            bj[ss-(m-mm)][nn][mm+(m-mm)]=bj[ss][nn][mm]+1;
            duis.push(ss-(m-mm));
            duin.push(nn);
            duim.push(mm+(m-mm));
        }
        if (bj[ss+(s-ss)][nn-(s-ss)][mm]==0&&ss+(s-ss)<=s&&nn-(s-ss)>=0)
        {
            bj[ss+(s-ss)][nn-(s-ss)][mm]=bj[ss][nn][mm]+1;
            duis.push(ss+(s-ss));
            duin.push(nn-(s-ss));
            duim.push(mm);
        }
        if (bj[ss][nn-(m-mm)][mm+(m-mm)]==0&&nn-(m-mm)>=0&&mm+(m-mm)<=m)
        {
            bj[ss][nn-(m-mm)][mm+(m-mm)]=bj[ss][nn][mm]+1;
            duis.push(ss);
            duin.push(nn-(m-mm));
            duim.push(mm+(m-mm));
        }
        if (bj[ss+(s-ss)][nn][mm-(s-ss)]==0&&ss+(s-ss)<=s&&mm-(s-ss)>=0)
        {
            bj[ss+(s-ss)][nn][mm-(s-ss)]=bj[ss][nn][mm]+1;
            duis.push(ss+(s-ss));
            duin.push(nn);
            duim.push(mm-(s-ss));
        }
        if (bj[ss][nn+(n-nn)][mm-(n-nn)]==0&&nn+(n-nn)<=n&&mm-(n-nn)>=0)
        {
            bj[ss][nn+(n-nn)][mm-(n-nn)]=bj[ss][nn][mm]+1;
            duis.push(ss);
            duin.push(nn+(n-nn));
            duim.push(mm-(n-nn));
        }

        if (nn<=s-ss&&bj[ss+nn][0][mm]==0)
        {
            bj[ss+nn][0][mm]=bj[ss][nn][mm]+1;
            //printf("%d\n", bj[ss-(n-nn)][nn+(n-nn)][mm]);
            duis.push(ss+n);
            duin.push(0);
            duim.push(mm);
        }
        if (mm<=s-ss&&bj[ss+mm][nn][0]==0)
        {
            bj[ss+mm][nn][0]=bj[ss][nn][mm]+1;
            //printf("%d\n", bj[ss-(n-nn)][nn+(n-nn)][mm]);
            duis.push(ss+mm);
            duin.push(nn);
            duim.push(0);
        }
        if (ss<=n-nn&&bj[0][ss+nn][mm]==0)
        {
            bj[0][nn+ss][mm]=bj[ss][nn][mm]+1;
            duis.push(0);
            duin.push(nn+ss);
            duim.push(mm);
        }
        if (mm<=n-nn&&bj[ss][nn+mm][0]==0)
        {
            bj[ss][nn+mm][0]=bj[ss][nn][mm]+1;
            duis.push(ss);
            duin.push(nn+mm);
            duim.push(0);
        }
        if (ss<=m-mm&&bj[0][nn][mm+ss]==0)
        {
            bj[0][nn][mm+ss]=bj[ss][nn][mm]+1;
            duis.push(0);
            duin.push(nn);
            duim.push(mm+ss);
        }
        if (nn<=m-mm&&bj[ss][0][mm+nn]==0)
        {
            bj[ss][0][mm+nn]=bj[ss][nn][mm]+1;
            duis.push(ss);
            duin.push(0);
            duim.push(mm+nn);
        }
        duis.pop();
        duin.pop();
        duim.pop();
    }
    printf("NO\n");
    return ;
}
int main()
{
    while (scanf("%d %d %d",&s,&n,&m)&&s!=0&&n!=0&&m!=0)
    {
        memset(bj,0,sizeof(bj));
        if (s%2==1)
        {
            printf("NO\n");
            continue;
        }else
        {
            while (!duis.empty()&&!duin.empty()&&!duim.empty())
            {
                duis.pop();
                duin.pop();
                duim.pop();
            }
            k=s/2;
            bj[s][0][0]=0;
            duis.push(s);
            duin.push(0);
            duim.push(0);
            bfs();
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值