非常可乐(HDOJ 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

My Code

#include 
#include 
#include 
using namespace std;
int v[105][105][105];       //标记每种状态是否出现过
int a[3];                   //a[0]是S,a[1]是N,a[2]是M
int half;                   //半瓶水的体积
struct node
{
    int V[3];               //跟a数组一样
    int step;
};
bool check(node p)          //判断是否平分了
{
    if (p.V[0] == half && p.V[1] == half)
        return true;
    if (p.V[0] == half && p.V[2] == half)
        return true;
    if (p.V[1] == half && p.V[2] == half)
        return true;
    return false;
}
void bfs()
{
    if (a[0] % 2)           //既然都是整数,显然倒不出0.5来
    {                       //所以奇数剪了
        cout << "NO" << endl;
        return;
    }
    memset(v, 0, sizeof(v));
    queue q;
    node p, next;
    half = a[0] >> 1;
    p.V[0] = a[0];
    p.V[1] = 0;
    p.V[2] = 0;
    p.step=0;
    v[p.V[0]][p.V[1]][p.V[2]] = 1;
    q.push(p);
    while (!q.empty())
    {
        p = q.front();
        q.pop();
        for (int i = 0; i < 3; i++)
        {
            if (p.V[i] > 0)    //倒之前总得有可乐
            {
                for (int j = 0; j < 3; j++)
                {
                    if (i == j || p.V[j] == a[j])
                        continue;       //显然不能倒给自己也不能给满的杯子倒
                    next = p;           //这个千万别忘了
                    if (next.V[i] > a[j] - next.V[j])//能倒满的情况
                    {
                        next.V[i] -= a[j] - next.V[j];
                        next.V[j] = a[j];
                    }
                    else                            //倒不满或刚好倒满的情况
                    {
                        next.V[j] += next.V[i];
                        next.V[i] = 0;
                    }

                    if (!v[next.V[0]][next.V[1]][next.V[2]])
                    {
                        next.step++;
                        if (check(next))
                        {
                            cout << next.step << endl;
                            return;
                        }
                        v[next.V[0]][next.V[1]][next.V[2]] = 1;
                        q.push(next);
                    }
                }
            }
        }
    }
    cout << "NO" << endl;
}
int main()
{
    while (cin >> a[0] >> a[1] >> a[2])
    {
        if (!(a[0] && a[1] && a[2]))
            break;
        bfs();
    }
    return 0;
}