HDU ~ 1495 ~ 非常可乐(BFS)

思路:bfs。倒水共有6中情况既(A->B,A->C),(B->A,B->C),(C->A,C->B),我们可以写一个双重循环来模拟这六种情况(当然你也可以把这六种情况一一写出来)。当 i -> j,i给j倒水的时候有两种情况,① i 可以把 j 给装满 ② i 装不满 j 。两种情况不一样记得判断一下即可。标记数组开为3维,每一个维度表示一个杯子。

注意:结束条件为严格的有两个杯子中有S/2的水(比如对于样例二,2 1 1不算结束,必须的2 0 2才可以),且判断条件不能写成S/2,因为7/3 == 2会出错。

#include<bits/stdc++.h>
using namespace std;
int S[5];
struct Node
{
    int cup[3],step;
}NOW, NEXT;
bool vis[105][105][105];
int bfs()
{
    memset(vis, 0, sizeof(vis));
    queue<Node> q;
    NOW.cup[0] = S[0]; NOW.cup[1] = 0; NOW.cup[2] = 0; NOW.step = 0;
    vis[S[0]][0][0] = true;
    q.push(NOW);
    while (!q.empty())
    {
        NOW = q.front();
        q.pop();
        if ((NOW.cup[0] * 2 == S[0] && NOW.cup[1] * 2 == S[0]) ||
            (NOW.cup[0] * 2 == S[0] && NOW.cup[2] * 2 == S[0]) ||
            (NOW.cup[1] * 2 == S[0] && NOW.cup[2] * 2 == S[0]))
        {
            return NOW.step;
        }
        for (int i = 0; i < 3; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                if (i != j)
                {
                    NEXT = NOW;
                    if (NOW.cup[i] >= S[j] - NOW.cup[j])//i能倒满j
                    {
                        NEXT.cup[i] = NOW.cup[i] - (S[j] - NOW.cup[j]);
                        NEXT.cup[j] = S[j];
                    }
                    else
                    {
                        NEXT.cup[i] = 0;
                        NEXT.cup[j] = NOW.cup[i] + NOW.cup[j];
                    }
                    NEXT.step = NOW.step + 1;
                    if (!vis[NEXT.cup[0]][NEXT.cup[1]][NEXT.cup[2]])
                    {
                        vis[NEXT.cup[0]][NEXT.cup[1]][NEXT.cup[2]] = true;
                        q.push(NEXT);
                    }
                }
            }
        }
    }
    return -1;
}
int main()
{
    while (~scanf("%d%d%d",&S[0], &S[1], &S[2]) && (S[0] + S[1] + S[2]))
    {
        int ans = bfs();
        if (ans != -1) printf("%d\n",ans);
        else printf("NO\n");
    }
    return 0;
}
/*
7 4 3
4 1 3
0 0 0
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值