HDU1495,广搜

其实这是一道比较常规的搜索题,思路也很符合搜索的想法(搜索其实就是暴力出所有结果,然后选取满足条件的结果);我感觉这题就难在写代码上;

好了,先说思路吧:首先对于这三个容器(s->可乐瓶,a->杯子1,b->杯子2),只有以下几种情况:s往a里到可乐,s往b里倒可乐,a往s里倒可乐,a往b里倒可乐,b往s里倒可乐,b往a里倒可乐。所以直接暴力BFS就行了(代码详解)

#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#include<cstdlib>
using namespace std;
int vis[105][105][105];//搜索标记用的,三维数组,没用过没关系,这里用的很简单
int n,x,y;//n可乐瓶的容积,x是杯子a的容积,y是杯子b的容积
struct node
{
    int s,a,b;
    int mov;
};//每个结构体,用来保存当前这种情况s,a,b中可乐的多少,mov表示由初始情况到这种情况需要倒的次数
queue<node>q;//BFS用的队列
int bfs(node start)
{
    while (!q.empty())
        q.pop();//队列清空
    q.push(start);//初始状态入队列
    while (!q.empty())
    {
        node tmp = q.front();
        q.pop();
        node next;
        if (tmp.s != 0)//s中有可乐(接下来往a,b中倒)
        {
            //下面是往a杯子中倒可乐
            if (tmp.s <= x - tmp.a)//x是a杯子的容积,tmp.a是该状态下,a容器中可乐的量,它们
                //的差就是a杯子中还能装多少可乐;这条判断的意思是,s中的可乐量小于a杯子还能装的可乐量
            {
                //s往a中倒完之后的状态就是:
                next.s = 0;
                next.a = tmp.a + tmp.s;
                next.b = tmp.b;
            }
            else//这条判断的意思是,s中的可乐量大于于a杯子还能装的可乐量
            {
                next.s = tmp.s - (x-tmp.a);
                next.a = x;
                next.b = tmp.b;
            }
            next.mov = tmp.mov + 1;//由刚开始状态到倒完之后的状态,倒的次数+1
            if ((n/2 == next.s && next.s == next.a) || (n/2 == next.s && next.s == next.b) || (n/2 == next.a && next.a == next.b))
            {
                //这条判断就是看在倒完之后得到的状态下,有没有两个容器中可乐的量都=n/2的
                return next.mov;
            }
            if (!vis[next.s][next.a][next.b])//如果没有两个容器中可乐的量都=n/2的话,就入队列,同时标记一下这种状态
            {
                q.push(next);
                vis[next.s][next.a][next.b] = 1;
            }
            //下面是s往b中倒可乐,情况同上
            if (tmp.s <= y - tmp.b)
            {
                next.s = 0;
                next.a = tmp.a;
                next.b = tmp.s + tmp.b;
            }
            else
            {
                next.s = tmp.s - (y-tmp.b);
                next.a = tmp.a;
                next.b = y;
            }
            next.mov = tmp.mov + 1;
            if ((n/2 == next.s && next.s == next.a) || (n/2 == next.s && next.s == next.b) || (n/2 == next.a && next.a == next.b))
            {
                return next.mov;
            }
            if (!vis[next.s][next.a][next.b])
            {
                q.push(next);
                vis[next.s][next.a][next.b] = 1;
            }
        }
        if (tmp.a != 0)//a中有可乐(接下来往s,b中倒)
        {
            //下面是a往b中倒可乐
            if (tmp.a <= y - tmp.b)
            {
                next.a = 0;
                next.b = tmp.a + tmp.b;
            }
            else
            {
                next.a = tmp.a - (y-tmp.b);
                next.b = y;
            }
            next.s = tmp.s;
            next.mov = tmp.mov + 1;
            if ((n/2 == next.s && next.s == next.a) || (n/2 == next.s && next.s == next.b) || (n/2 == next.a && next.a == next.b))
            {
                return next.mov;
            }
            if (!vis[next.s][next.a][next.b])
            {
                q.push(next);
                vis[next.s][next.a][next.b] = 1;
            }
            //下面是a往s中倒可乐
            next.s = tmp.s + tmp.a;
            next.a = 0;
            next.b = tmp.b;
            next.mov = tmp.mov + 1;
            if ((n/2 == next.s && next.s == next.a) || (n/2 == next.s && next.s == next.b) || (n/2 == next.a && next.a == next.b))
            {
                return next.mov;
            }
            if (!vis[next.s][next.a][next.b])
            {
                q.push(next);
                vis[next.s][next.a][next.b] = 1;
            }
        }
        if (tmp.b != 0)//所有情况和上面两种情况一样
        {
            if (tmp.b <= x - tmp.a)
            {
                next.a = tmp.a + tmp.b;
                next.b = 0;
            }
            else
            {
                next.a = x;
                next.b = tmp.b - (x-tmp.a);
            }
            next.s = tmp.s;
            next.mov = tmp.mov + 1;
            if ((n/2 == next.s && next.s == next.a) || (n/2 == next.s && next.s == next.b) || (n/2 == next.a && next.a == next.b))
            {
                return next.mov;
            }
            if (!vis[next.s][next.a][next.b])
            {
                q.push(next);
                vis[next.s][next.a][next.b] = 1;
            }
            next.s = tmp.s + tmp.b;
            next.a = tmp.a;
            next.b = 0;
            next.mov = tmp.mov + 1;
            if ((n/2 == next.s && next.s == next.a) || (n/2 == next.s && next.s == next.b) || (n/2 == next.a && next.a == next.b))
            {
                return next.mov;
            }
            if (!vis[next.s][next.a][next.b])
            {
                q.push(next);
                vis[next.s][next.a][next.b] = 1;
            }
        }
    }
    return -1;//如果在这之前函数没有返回值的话,说明不可均分
}
int main()
{
    while (~scanf("%d%d%d",&n,&x,&y))
    {
        if (n+x+y == 0)
            break;
        if(n % 2 != 0)
        {
            printf("NO\n");
            continue;
        }
        //这三个容器的体积都是整数,所以可乐体积的一半如果是小数的话,每人是不可能分到的,就输出NO
        memset(vis,0,sizeof(vis));//标记数组先都清成0
        node tmp;//建立一个节点,保存最开始的状态
        tmp.s = n;//最开始,所有可乐在s中
        tmp.a = 0;//最开始,a杯子中没有可乐
        tmp.b = 0;//最开始,b杯子中没有可乐
        tmp.mov = 0;//倒的次数为0
        vis[n][x][y] = 1;//标记数组的三个数分别就是s,a,b中的可乐量
        int ans = bfs(tmp);
        if (ans == -1)//返回-1,表明了不可均分
            printf("NO\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值