NYOJ-21-三个水杯

描述
给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子。三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算。现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数。

输入
第一行一个整数N(0< N <50)表示N组测试数据
接下来每组测试数据有两行,第一行给出三个整数V1 V2 V3 (V1>V2>V3 V1<100 V3>0)表示三个水杯的体积。
第二行给出三个整数E1 E2 E3 (体积小于等于相应水杯体积)表示我们需要的最终状态

输出
每行输出相应测试数据最少的倒水次数。如果达不到目标状态输出-1

样例输入
2
6 3 1
4 1 1
9 3 2
7 1 1

样例输出
3
-1

这是一道经典的bfs,虽然代码篇幅很长,但是原理很简单,也容易理解。

#include <stdio.h>

typedef struct State
{
    int Ei;
    int Ej;
    int Ek;
    int Step;
} State;

State S[5050];

int V1, V2, V3;
int E1, E2, E3;
int head, tail;

void init()
{
    S[0].Ei = V1;
    S[0].Ej = 0;
    S[0].Ek = 0;
    S[0].Step = 0;
    head = 0;
    tail = 1;
}

int haveSame()
{
    int i;
    for (i = 0; i < tail; i++)
    {
        if (S[i].Ei == S[tail].Ei && S[i].Ej == S[tail].Ej && S[i].Ek == S[tail].Ek)
        {
            return 1;
        }
    }
    return 0;
}

int judge(int Ei, int Ej, int Ek, int Step)
{
    if (Ei == E1 && Ej == E2 && Ek == E3)
    {
        printf("%d\n", Step);
        return 1;
    }
    return 0;
}

//BFS
void solve()
{
    if (judge(S[0].Ei, S[0].Ej, S[0].Ek, S[0].Step))
    {
        return ;
    }
    while (head < tail)
    {
        if (S[head].Ei > 0)
        {
            //第一个杯子往第二个杯子里倒
            if (S[head].Ej < V2)
            {
                S[tail].Ek = S[head].Ek;
                S[tail].Ej = S[head].Ei > V2 - S[head].Ej ? V2 : S[head].Ei + S[head].Ej;
                S[tail].Ei = S[head].Ei > V2 - S[head].Ej ? S[head].Ei - V2 + S[head].Ej : 0;
                S[tail].Step = S[head].Step + 1;
                if (judge(S[tail].Ei, S[tail].Ej, S[tail].Ek, S[tail].Step))
                {
                    return ;
                }
                if (!haveSame())
                {
                    tail++;
                }
            }
            //第一个杯子往第三个杯子里倒
            if (S[head].Ek < V3)
            {
                S[tail].Ej = S[head].Ej;
                S[tail].Ek = S[head].Ei > V3 - S[head].Ek ? V3 : S[head].Ei + S[head].Ek;
                S[tail].Ei = S[head].Ei > V3 - S[head].Ek ? S[head].Ei - V3 + S[head].Ek : 0;
                S[tail].Step = S[head].Step + 1;
                if (judge(S[tail].Ei, S[tail].Ej, S[tail].Ek, S[tail].Step))
                {
                    return ;
                }
                if (!haveSame())
                {
                    tail++;
                }
            }
        }
        if (S[head].Ej > 0)
        {
            //第二个杯子往第一个杯子里倒
            if (S[head].Ei < V1)
            {
                S[tail].Ek = S[head].Ek;
                S[tail].Ei = S[head].Ej > V1 - S[head].Ei ? V1 : S[head].Ej + S[head].Ei;
                S[tail].Ej = S[head].Ej > V1 - S[head].Ei ? S[head].Ej - V1 + S[head].Ei : 0;
                S[tail].Step = S[head].Step + 1;
                if (judge(S[tail].Ei, S[tail].Ej, S[tail].Ek, S[tail].Step))
                {
                    return ;
                }
                if (!haveSame())
                {
                    tail++;
                }
            }
            //第二个杯子往第三个杯子里倒
            if (S[head].Ek < V3)
            {
                S[tail].Ei = S[head].Ei;
                S[tail].Ek = S[head].Ej > V3 - S[head].Ek ? V3 : S[head].Ej + S[head].Ek;
                S[tail].Ej = S[head].Ej > V3 - S[head].Ek ? S[head].Ej - V3 + S[head].Ek : 0;
                S[tail].Step = S[head].Step + 1;
                if (judge(S[tail].Ei, S[tail].Ej, S[tail].Ek, S[tail].Step))
                {
                    return ;
                }
                if (!haveSame())
                {
                    tail++;
                }
            }

        }
        if (S[head].Ek > 0)
        {
            //第三个杯子往第一个杯子里倒
            if (S[head].Ei < V1)
            {
                S[tail].Ej = S[head].Ej;
                S[tail].Ei = S[head].Ek > V1 - S[head].Ei ? V1 : S[head].Ek + S[head].Ei;
                S[tail].Ek = S[head].Ek > V1 - S[head].Ei ? S[head].Ek - V1 + S[head].Ei : 0;
                S[tail].Step = S[head].Step + 1;
                if (judge(S[tail].Ei, S[tail].Ej, S[tail].Ek, S[tail].Step))
                {
                    return ;
                }
                if (!haveSame())
                {
                    tail++;
                }
            }//第三个杯子往第二个杯子里倒
            if (S[head].Ej < V2)
            {
                S[tail].Ei = S[head].Ei;
                S[tail].Ej = S[head].Ek > V2 - S[head].Ej ? V2 : S[head].Ek + S[head].Ej;
                S[tail].Ek = S[head].Ek > V2 - S[head].Ej ? S[head].Ek - V2 + S[head].Ej : 0;
                S[tail].Step = S[head].Step + 1;
                if (judge(S[tail].Ei, S[tail].Ej, S[tail].Ek, S[tail].Step))
                {
                    return ;
                }
                if (!haveSame())
                {
                    tail++;
                }
            }
        }
        head++;
    }

    printf("-1\n");
    return ;
}

int main()
{
    int N;
    scanf("%d", &N);

    while (N--)
    {
        scanf("%d %d %d", &V1, &V2, &V3);
        scanf("%d %d %d", &E1, &E2, &E3);

        init();
        solve();
    }

    return 0;
}

最开始写这个代码时,因为忽略了一种情况,而WA了两遍。
比如说,
9 7 5
9 0 0

这需要倒的次数为0,直接进行初始条件的判断后即可输出结果为0,然而因为我缺乏对初始条件的判断,所以导致结果为2,有些可悲,一失足成千古恨。当然,加上这个初始条件的判断后,顺利AC了……

你可能感兴趣的:(bfs)