【USACO】milk3

倒牛奶的问题, 开始看感觉跟倒水的问题很像, 想直接找规律, 写个类似于循环取余的代码。 但后来发现不行,因为这道题有三个桶,水量也是有限制的。只好用模拟的方法把所有的情况都试一遍。

建一个state[21][21][21]的数组存储出现过的状态。对于遍历状态,对每一种状态, 分别采用六种处理方法,若有新状态出现这将新状态置为1,同时标记flag++;若所有循环之后,flag == 0, 就说明遍历完成了。

开始脑子抽筋了, 写了个多出口的程序, 显然是错的。如下:

int mothersmilk(int a, int b, int c)

{

    int aa, bb, cc;

    int flag = 0;



    aa = a, bb = b, cc = c;

    pour(&aa, A, &bb, B);

    if(state[aa][bb][cc] != 1)

    {

        state[aa][bb][cc] = 1;

        mothersmilk(aa, bb, cc); //

        flag++;

    }



    aa = a, bb = b, cc = c;

    pour(&bb, B, &aa, A);

    if(state[aa][bb][cc] != 1)

    {

        state[aa][bb][cc] = 1;

        mothersmilk(aa, bb, cc);

    }



    aa = a, bb = b, cc = c;

    pour(&aa, A, &cc, C);

    if(state[aa][bb][cc] != 1)

    {

        state[aa][bb][cc] = 1;

        mothersmilk(aa, bb, cc); //

    }



    aa = a, bb = b, cc = c;

    pour(&cc, C, &aa, A);

    if(state[aa][bb][cc] != 1)

    {

        state[aa][bb][cc] = 1;

        mothersmilk(aa, bb, cc);

    }



    aa = a, bb = b, cc = c;

    pour(&bb, B, &cc, C);

    if(state[aa][bb][cc] != 1)

    {

        state[aa][bb][cc] = 1;

        mothersmilk(aa, bb, cc); //

    }



    aa = a, bb = b, cc = c;

    pour(&cc, C, &bb, B);

    if(state[aa][bb][cc] != 1)

    {

        state[aa][bb][cc] = 1;

        mothersmilk(aa, bb, cc); //

    }
  return 0;
//... }

错误的原因在于,若是第一个if语句中的mothersmilk操作完了,一定会返回0,那后面的语句都起不到作用了。

 

后来发现,可以直接对所有的state变量循环,用for语句,逻辑就清楚多了,提交也AC了。正确的代码:

/*

ID: 13012131

LANG: C

TASK: milk3

*/



#include <stdio.h>

#include <assert.h>



int state[21][21][21];  //存储状态 出现过为1 未出现过为0

int A, B, C;



int pour(int *a, int fulla, int *b, int fullb) //a向b倒水

{

    if(*b == fullb || *a == 0) //若a没水 或 b满 a不能向b倒水 状态不变

    {

        return 1;

    }

    if(*b != fullb) //b不满

    {

        if(*a <= fullb - *b) //a倒光

        {

            *b = *b + *a;

            *a = 0;

        }

        else  //b倒满

        {

            *a = *a - (fullb - *b);

            *b = fullb;

        }

    }

    return 0;

}





int main()

{

    FILE *in, *out;

    in = fopen("milk3.in", "r");

    out = fopen("milk3.out", "w");

    int ans[21] = {0};

    int i, j ,k;

    

    fscanf(in, "%d %d %d", &A, &B, &C);



    for(i = 0; i <= 20; i++)

    {

        for(j = 0; j <= 20; j++)

        {

            for(k = 0; k <= 20; k++)

            {

                state[i][j][k] = 0;

            }

        }

    }

    state[0][0][C] = 1;



    int flag = 0;

    do{

        flag = 0;   //注意:flag一定要写在这里 因为在扩展过程中,需要对state的所有状态循环多次 以防止在大序号状态下扩展了小序号状态 比如 2 0 8 扩展为 0 2 8 因为0 2 8的状态已经超过了 所以还要重新遍历一遍才可以

        for(i = 0; i <= A; i++)

        {

            for(j = 0; j <= B; j++)

            {

                for(k = 0; k <= C; k++)

                {

                    if(state[i][j][k] == 1)

                    {

                        int aa, bb, cc;

                        aa = i, bb = j, cc = k;

                        pour(&aa, A, &bb, B);

                        if(state[aa][bb][cc] == 0)

                        {

                            state[aa][bb][cc] = 1;

                            flag++;

                        }



                        aa = i, bb = j, cc = k;

                        pour(&bb, B, &aa, A);

                        if(state[aa][bb][cc] == 0)

                        {

                            state[aa][bb][cc] = 1;

                            flag++;

                        }



                        aa = i, bb = j, cc = k;

                        pour(&aa, A, &cc, C);

                        if(state[aa][bb][cc] == 0)

                        {

                            state[aa][bb][cc] = 1;

                            flag++;

                        }



                        aa = i, bb = j, cc = k;

                        pour(&cc, C, &aa, A);

                        if(state[aa][bb][cc] == 0)

                        {

                            state[aa][bb][cc] = 1;

                            flag++;

                        }



                        aa = i, bb = j, cc = k;

                        pour(&bb, B, &cc, C);

                        if(state[aa][bb][cc] == 0)

                        {

                            state[aa][bb][cc] = 1;

                            flag++;

                        }



                        aa = i, bb = j, cc = k;

                        pour(&cc, C, &bb, B);

                        if(state[aa][bb][cc] == 0)

                        {

                            state[aa][bb][cc] = 1;

                            flag++;

                        }

                        state[i][j][k]++;

                    }

                    

                }

            }

        }

    }while(flag > 0);







        for(j = 0; j <= 20; j++)

        {

            for(k = 0; k <= 20; k++)

            {

                if(state[0][j][k] != 0 && ans[k] == 0)

                {

                    ans[k] = 1;

                }

            }

        }



    for(i = 0; i < C; i++)

    {

        if(ans[i] == 1)

        {

            fprintf(out, "%d ", i);

        }

    }

    fprintf(out, "%d\n", C);



    return 0;

}

 

你可能感兴趣的:(USACO)