杯子倒水

来源:互联网 发布:手机怎么注册不了淘宝 编辑:程序博客网 时间:2024/04/27 13:51

http://acm.pku.edu.cn/JudgeOnline/problem?id=1606

/**
 * <problem>
 *
 *                            Jugs
 *   In the movie "Die Hard 3", Bruce Willis and Samuel L. Jackson were
 * confronted with the following puzzle. They were given a 3-gallon jug
 * and a 5-gallon jug and were asked to fill the 5-gallon jug with exactly
 * 4 gallons. This problem generalizes that puzzle.
 *
 *   You have two jugs, A and B, and an infinite supply of water. There are
 * three types of actions that you can use: (1) you can fill a jug, (2) you
 * can empty a jug, and (3) you can pour from one jug to the other. Pouring
 * from one jug to the other stops when the first jug is empty or the second
 * jug is full, whichever comes first. For example, if A has 5 gallons and B
 * has 6 gallons and a capacity of 8, then pouring from A to B leaves B full
 * and 3 gallons in A.
 *
 *   A problem is given by a triple (Ca,Cb,N), where Ca and Cb are the
 * capacities of the jugs A and B, respectively, and N is the goal. A
 * solution is a sequence of steps that leaves exactly N gallons in jug
 * B. The possible steps are
 *      fill A
 *      fill B
 *      empty A
 *      empty B
 *      pour A B
 *      pour B A
 *      success
 *   where "pour A B" means "pour the contents of jug A into jug B", and
 * "success" means that the goal has been accomplished.
 *   You may assume that the input you are given does have a solution.
 *
 * Input
 *   Input to your program consists of a series of input lines each defining
 * one puzzle. Input for each puzzle is a single line of three positive
 * integers: Ca, Cb, and N. Ca and Cb are the capacities of jugs A and B,
 * and N is the goal. You can assume 0 < Ca <= Cb and N <= Cb <=1000 and that
 * A and B are relatively prime to one another.
 
 * Output
 *   Output from your program will consist of a series of instructions from
 * the list of the potential output lines which will result in either of the
 * jugs containing exactly N gallons of water. The last line of output for
 * each puzzle should be the line "success". Output lines start in column 1
 * and there should be no empty lines nor any trailing spaces.
 *
 * Sample Input
 * 3 5 4
 * 5 7 3
 *
 * Sample Output
 * fill B
 * pour B A
 * empty A
 * pour B A
 * fill B
 * pour B A
 * success
 * fill A
 * pour A B
 * fill A
 * pour A B
 * empty B
 * pour A B
 * success
 *
 * </problem>
 *
 * @author bbflyerwww
 */

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

#define MAX 10000
char s[][10] = {"fill A",
    "fill B",
    "empty A",
    "empty B",
    "pour A B",
    "pour B A",
    "success"
};
char rs[MAX][10];
int k;
int ca, cb, n;

int main()
{
    int va, vb;
    while(scanf("%d %d %d", &ca, &cb, &n) != EOF) {
        //init some parameters
        va = 0;
        vb = 0;
        k = -1;
        //kernel
        while(1) {
            if(va == 0) {
                //fill A while va == 0
                va = ca;
                k ++;
                strcpy(rs[k], s[0]);
            } else {
                //do something else while va != 0
                if(va > cb - vb) {
                    // va > cb - vb
                    va = va - (cb - vb);
                    vb = cb;
                    //pour A to B
                    k ++;
                    strcpy(rs[k], s[4]);
                    //break while vb == n notice that vb = cb now  
                    if(vb == n)   goto end;//break;
                    //empty B while vb != n
                    vb = 0;
                    k++;
                    strcpy(rs[k], s[3]);
                } else {
                    // va < cb - vb
                    vb += va;
                    va = 0;
                    //pour A to B
                    k ++;
                    strcpy(rs[k], s[4]);
                    //break while vb == n notice that vb may be not full
                    if(vb == n) goto end;//break;
                }
            }
        }
        end:
        //success
        k++;
        strcpy(rs[k], s[6]);
        //show the result
        for(int i = 0; i <= k; i++)
            printf("%s/n", rs[i]);
       
    }
    return 0;
}

  附加:  灌水定理 
    如果有n个壶容积分别为A1,A2,……,An(Ai均为大于0的整数)
  设w为另一大于0的整数。则用此n个壶可倒出w升水的充要条件为:   
  1)w小于等于A1+A2+……+An;   
  2)w可被(A1,A2,……,An)(这n个数的最大公约数)整除。