HDU 1495 非常可樂(BFS)

非常可樂

大家一定覺的運動以後喝可樂是一件很愜意的事情,但是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

題意:
三個杯子已知容量,只有一杯可樂,來回倒,問多少次能把可樂均分成兩份
題意很簡單的,關鍵是思路

思路:
倒的過程只有六種,即6個方向,要求的操作數類似於其他bfs要求的步數
把題中的s n m用數組存,來回倒的過程就能用裏外兩個循環寫,方便一點

純C的代碼:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int b[5];
struct node
{
    int a[5];
    int step;
} str[1005], x, y;
int vis[105][105][105];

void bfs(int s)
{
    if(s%2!=0) printf("NO\n");
    else if(b[1]==s/2) printf("1\n");
    else
    {
        int i, j, in, out;
        in = 0;
        out = 0;
        x.a[0] = s;
        x.a[1] = 0;
        x.a[2] = 0;
        x.step = 0;
        str[in++] = x;
        while(in>out)
        {
            x = str[out++];  //得到最末尾的一個狀態
            for(i=0; i<3; i++)    //x.a[i]往外倒
            {
                if(x.a[i]==0) continue;  //有的倒
                for(j=0; j<3; j++)    //x.a[j]往裏接
                {
                    if(i==j) continue;    //不能一個杯子操作!(一開始這裏也沒寫,樣例能過,但是代碼不對)
                    y = x;
                    if(x.a[i]+x.a[j] >= b[j])  //能倒滿
                    {                          //注意裏面式子都是不能倒過來的
                        y.a[i] = x.a[i] + x.a[j] - b[j];
                        y.a[j] = b[j];
                    }
                    else  //不能倒滿
                    {
                        y.a[j] = x.a[i] + x.a[j];
                        y.a[i] = 0;
                    }
                    if(vis[y.a[0]][y.a[1]][y.a[2]]==0)   //如果這個狀態是新的,判斷+進隊列
                    {
                        y.step++;
                        if((y.a[0]==b[0]/2&&y.a[1]==b[0]/2)  //一開始把判斷寫在判斷上面的x了,
                                  //每次判斷最後一個,超時了。應該是得到一個狀態就判斷
                                  //避免後知後覺做了一些無謂的動作
                                ||(y.a[0]==b[0]/2&&y.a[2]==b[0]/2)
                                ||(y.a[1]==b[0]/2&&y.a[2]==b[0]/2)
                          )
                        {
                            printf("%d\n", y.step);
                            return;
                        }
                        str[in++] = y;
                        vis[y.a[0]][y.a[1]][y.a[2]] = 1;
                    }
                }
            }
        }
        printf("NO\n");
    }
}

int main()
{
    while(~scanf("%d %d %d", &b[0], &b[1], &b[2]))
    {
        if(!b[0]&&!b[1]&&!b[2]) break;
        memset(vis, 0, sizeof(vis));
        vis[b[0]][0][0] = 1;
        bfs(b[0]);
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章