[HDU1495]非常可乐

题目描述

大家一定觉得运动以后喝可乐是一件很惬意的事情,但是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到尽头就行了。实际上就是从初始状态延伸出来的一棵解答树,我们去一层一层地搜。

剩下的见代码注释。

//PS:自己写的,代码有点粗糙,vJudge上面跑了七百多,未优化
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>

using namespace std;

const int N = 120;
int s,n,m;
typedef struct Node
{
    int x;
    int y;
    int z;
} V;//开一个结构体数组用来定义队列
queue<V> q;
int d[N][N][N];
void pour(int &x1,int &x2,int m)//模拟倒水操作,这里注意要先倒水再清空瓶子,即x2 += x1;x2 = m;两个步骤不能反了
{
    if(x1<(m-x2))
    {
        x2 += x1;
        x1 = 0;
    }
    else
    {
        x1 -= (m-x2);
        x2 = m;
    }
}
int Mymin(int x,int y,int z)//这里是一个小瑕疵
{
    if(x == -1) x = 100000;
    if(y == -1) y = 100000;
    if(z == -1) z = 100000;
    int t1 = min(x,y);
    int t = min(t1,z);
    return t;
}
int bfs()
{
    memset(d,-1,sizeof d);
    d[s][0][0] = 0;
    V e;
    e.x = s,e.y = 0,e.z = 0;
    q.push(e);//把初始状态入队扩展
    while (!q.empty())//队列不空就一直扩展
    {
        V t = q.front();
        q.pop();
        V k = t;
        
        if(k.x>0)
        {
            pour(k.x,k.y,n);
            if (d[k.x][k.y][k.z] == -1)
            {
                q.push(k);
                d[k.x][k.y][k.z] = d[t.x][t.y][t.z] + 1;
            }
            k = t;
            pour(k.x,k.z,m);
            if (d[k.x][k.y][k.z] == -1)
            {
                q.push(k);
                d[k.x][k.y][k.z] = d[t.x][t.y][t.z] + 1;
            }
        }
        k = t;
        if(k.y>0)
        {
            pour(k.y,k.x,s);
            if (d[k.x][k.y][k.z] == -1)
            {
                q.push(k);
                d[k.x][k.y][k.z] = d[t.x][t.y][t.z] + 1;
            }
            k = t;
            pour(k.y,k.z,m);
            if (d[k.x][k.y][k.z] == -1)
            {
                q.push(k);
                d[k.x][k.y][k.z] = d[t.x][t.y][t.z] + 1;
            }
        }
        k = t;
        if(k.z>0)
        {

            pour(k.z,k.y,n);
            if(d[k.x][k.y][k.z] == -1)
            {
                q.push(k);
                d[k.x][k.y][k.z] = d[t.x][t.y][t.z] + 1;
            }
            k = t;
            pour(k.z,k.x,s);
            if(d[k.x][k.y][k.z] == -1)
            {
                q.push(k);
                d[k.x][k.y][k.z] = d[t.x][t.y][t.z] + 1;
            }
        }
    }
    int ans = Mymin(d[s/2][s/2][0],d[s/2][0][s/2],d[0][s/2][s/2]);
    return ans;
}

int main()
{
    while (1)
    {
        cin>>s>>n>>m;
        if(s == 0&&n == 0&&m == 0) break;
        if(s%2)
        {
            printf("NO\n");
            continue;
        }
        int res = bfs();
        if(res == -1||res == 100000) printf("NO\n");
        else printf("%d\n",res);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Trouni/p/12663794.html