2015/06/21

【UVa】10603-FILL 倒水問題 (BFS)




題目連結

題目大意:
有a, b, c三杯水,每杯水都有容量限制。倒法是一杯水到另一杯水倒到自己空或是別人滿為止。題目輸入為a, b, c, d,求要得到d公升的水,總共需要倒幾公升的水,若無法倒到d,求最近值。起始狀態為,a, b為空,c為滿。

題目思路:
BFS的經典倒水問題。我一開始開三維陣列去紀錄a,b,c的水量,但TLE。後來才想到,因為a+b+c的水量是一定的,所以開二維陣列就ok

Code

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <cstdio>
#include <queue>
#define N 201
 
using namespace std;
 
struct state{
    int a, b, c, total;
};
struct state s;
int a_vol, b_vol, c_vol, d, ans;
int jugs[N][N], record[N];/*紀錄哪個數字出現的時候,那時的總水量*/
 
void init(){
    for (int i=0; i<=a_vol; i++) {
        for (int j=0; j<=b_vol; j++)
                jugs[i][j] = -1;
    }
    for (int i=0; i< N; i++) record[i] = -1;
}
 
struct state build_s(int a, int b, int c, int total){
    struct state tmp;
    tmp.a = a, tmp.b = b, tmp.c = c, tmp.total = total;
    return tmp;
}
 
void bfs(){
    queue< struct state> q;
    s.a = 0, s.b = 0, s.c = c_vol, s.total = 0;
    q.push(s);
    while (!q.empty()) {
        struct state tmp = q.front();
        q.pop();
        int a = tmp.a, b = tmp.b, c = tmp.c, total = tmp.total;
        if (total >= record[d] && record[d]!=-1) continue;
        if (total >= jugs[a][b] && jugs[a][b]!=-1) continue;
        jugs[a][b] = total;
        record[a] = (record[a]==-1)?total:(record[a]< total)?record[a]:total;
        record[b] = (record[b]==-1)?total:(record[b]< total)?record[b]:total;
        record[c] = (record[c]==-1)?total:(record[c]< total)?record[c]:total;
        /*A->B*/
        if (a < b_vol-b) tmp = build_s(0, b+a, c, total+a);
        else tmp = build_s(a-(b_vol-b), b_vol, c, total+b_vol-b);
        q.push(tmp);
        /*A->C*/
        if (a < c_vol-c) tmp = build_s(0, b, c+a, total+a);
        else tmp = build_s(a-(c_vol-c), b, c_vol, total+(c_vol-c));
        q.push(tmp);
        /*B->A*/
        if (b < a_vol-a) tmp = build_s(a+b, 0, c, total+b);
        else tmp = build_s(a_vol, b-(a_vol-a), c, total+(a_vol-a));
        q.push(tmp);
        /*B->C*/
        if (b < c_vol-c) tmp = build_s(a, 0, c+b, total+b);
        else tmp = build_s(a, b-(c_vol-c), c_vol, total+(c_vol-c));
        q.push(tmp);
        /*C->A*/
        if (c < a_vol-a) tmp = build_s(a+c, b, 0, total+c);
        else tmp = build_s(a_vol, b, c-(a_vol-a), total+(a_vol-a));
        q.push(tmp);
        /*C->B*/
        if (c < b_vol-b) tmp = build_s(a, c+b, 0, total+c);
        else tmp = build_s(a, b_vol, c-(b_vol-b), total+(b_vol-b));
        q.push(tmp);
    }
}
 
int main() {
    int n;
    scanf("%d", &n);
    while (n--) {
        scanf("%d %d %d %d", &a_vol, &b_vol, &c_vol, &d);
        init();
        bfs();
        int ans=d;
        while (record[ans]==-1) ans--;
        printf("%d %d\n", record[ans], ans);
    }
    return 0;
}