UVa 571. Jugs

2018-08-06

Description

在電影「終極警探 3(Die Hard 3)」中布魯斯威利(Bruce Willis)和山謬傑克森(Samuel L. Jackson)遇到壞蛋設下的謎題:給一個3加侖和5加侖的桶子,要求他們必須在5加侖的桶子中裝4加侖的水。現在你的任務就是解決這個問題。

給你2個桶子A、B和無限供應的水,你可以做3個動作:

  1. 把一個桶子裝滿水。
  2. 把一個桶子的水倒光。
  3. 把一個桶子的水倒到另一個桶子中。

把水從一個桶子倒到另一個桶子的動作停止有2個可能的原因:第一個桶子的水倒光了或第二個桶子的水滿了。例如:A有5加侖的水,B有6加侖的水且B的容量為8加侖,則當把A的水倒到B後,B就滿了(8加侖)而A中還剩3加侖。在本問題中,給你Ca,Cb,N。Ca,Cb分別代表A桶子和B桶子的容量而N是我們要求的目標。我們希望你的程式輸出一連串的動作之後,可以得到N加侖的水(不論在A或B中都可以)。這一連串的動作包含:

  • fill A
  • fill B
  • empty A
  • empty B
  • pour A B
  • pour B A
  • success

在這裡,“pour A B"代表把A的水倒到B中,而"success"代表任務已經完成了。你可以假設給你的輸入一定有解答。

Input Format

每組測試資料一列,含有3個正整數Ca,Cb,N。( $0 < \textrm{Ca} \le \textrm{Cb},\textrm{N} \le \textrm{Cb} \le 1000$ )

Output Format

每組測試資料輸出一連串的動作(總是以success作為結束),使得可以得到N加侖的水(不論在A或B中都可以)。請參考Sample Output。

Sample Input

3 5 4
5 7 3
1 1 1

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
success
fill A
success

UVa - 571
翻譯來源:Luckycat

Solution

這題可以利用BFS來做,每次都模擬6種操作,直到達成目標為止。
本題利用STL容器的Queue來模擬BFS。

Code

/*************************************************************************
  > File Name: 571 - Jugs.cpp
  > Author: Samuel
  > Mail: enminghuang21119@gmail.com
  > Created Time: Mon Jan 22 20:09:12 2018
*************************************************************************/

#include <iostream>
#include <queue>
#include <vector>
using namespace std;
struct node {
    int A, B;
    vector<int> moves;
};
bool state[1005][1005];
/*
 * 0 -> A fill
 * 1 -> B fill
 * 2 -> A -> B
 * 3 -> B -> A
 * 4 -> A empty
 * 5 -> B empty
*/
void out(int in) {
    switch (in) {
        case 0:
            cout << "fill A" << '\n'; break;
        case 1:
            cout << "fill B" << '\n'; break;
        case 2:
            cout << "pour A B" << '\n'; break;
        case 3:
            cout << "pour B A" << '\n'; break;
        case 4:
            cout << "empty A" << '\n'; break;
        case 5:
            cout << "empty B" << '\n'; break;
    }
}
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    int a, b, n;
    while (cin >> a >> b >> n) {
        node now, tmp;
        queue<node> que;
        now.A = now.B = 0;
        que.push(now);
        for (int i = 0; i < 1005; i++) for (int j = 0; j < 1005; j++) state[i][j] = 1;
        while (!que.empty()) {
            now = que.front();
            que.pop();
            if (now.B == n)
                 break;
            for (int i = 0; i < 6; i++) {
                tmp = now;
                tmp.moves.push_back(i);
                switch (i) {
                    case 0:
                        if (now.A < a) {
                            tmp.A = a;
                            que.push(tmp);
                            if (state[tmp.A][tmp.B]) {
                                que.push(tmp);
                                state[tmp.A][tmp.B] = 0;
                            }
                        }
                        break;
                    case 1:
                        if (now.B < b) {
                            tmp.B = b;
                            if (state[tmp.A][tmp.B]) {
                                que.push(tmp);
                                state[tmp.A][tmp.B] = 0;
                            }
                        }
                        break;
                    case 2:
                        if (now.B < b && now.A > 0) {
                            tmp.B += tmp.A;
                            tmp.A = 0;
                            if (tmp.B > b)
                                tmp.A = tmp.B - b, tmp.B = b;
                            if (state[tmp.A][tmp.B]) {
                                que.push(tmp);
                                state[tmp.A][tmp.B] = 0;
                            }
                        }
                        break;
                    case 3:
                        if (now.A < a && now.B > 0) {
                            tmp.A += tmp.B;
                            tmp.B = 0;
                            if (tmp.A > a)
                                tmp.B = tmp.A - a, tmp.A = a;
                            if (state[tmp.A][tmp.B]) {
                                que.push(tmp);
                                state[tmp.A][tmp.B] = 0;
                            }
                        }
                        break;
                    case 4:
                        if (now.A > 0) {
                            tmp.A = 0;
                            if (state[tmp.A][tmp.B]) {
                                que.push(tmp);
                                state[tmp.A][tmp.B] = 0;
                            }
                        }
                        break;
                    case 5:
                        if (now.B > 0) {
                            tmp.B = 0;
                            if (state[tmp.A][tmp.B]) {
                                que.push(tmp);
                                state[tmp.A][tmp.B] = 0;
                            }
                        }
                        break;
                }
            }
        }
        int size = now.moves.size();
        for (int i = 0; i < size; i++)
            out(now.moves[i]);
        cout << "success\n";
    }
    return 0;
}