0w1

UVA 10603 Fill ( PFS )

UVa Online Judge
題目要求用最少的水來往達到 d或接近 d,又注意到水不會減少亦不會增加,故狀態只有二維 ( 知道其中兩個分別裝了多少就能知道剩下的那個 ),這是一種隱式圖走訪的問題,可以用 PFS解決。

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 200 + 10;

int botmx[3], ans[MAXN];
bool vis[MAXN][MAXN];

struct State{
    int bot[3], cost;
    bool operator < (const State &b)const {
        return cost > b.cost; //so that small will come out first
    }
};
void update_ans(const State &s){
    for(int i = 0; i < 3; ++i){
        int d = s.bot[i];
        if( ans[d] == -1 || s.cost < ans[d] ) ans[d] = s.cost;
    }
}
void solve(int a, int b, int c, int d){
    botmx[0] = a, botmx[1] = b, botmx[2] = c;
    memset( vis, false, sizeof(vis) );
    memset( ans, -1, sizeof(ans) );
    priority_queue<State> pq;
    
    State start;
    start.cost = 0, start.bot[0] = start.bot[1] = 0, start.bot[2] = c;
    pq.push( start );
    vis[ 0 ][ 0 ] = true; //bot a = 0, b = 0

    while( !pq.empty() ){
        State s = pq.top(); pq.pop();
        update_ans( s );
        if( ans[d] >= 0 ) break;

        for(int i = 0; i < 3; ++i) //pours from i to j
            for(int j = 0; j < 3; ++j) if( i != j ){
                if( s.bot[i] == 0 || s.bot[j] == botmx[j] ) continue;
                int delta = min( s.bot[i], botmx[j] - s.bot[j] );
                State s2; memcpy( &s2, &s, sizeof(s) );
                s2.cost = s.cost + delta;
                s2.bot[i] = s.bot[i] - delta;
                s2.bot[j] = s.bot[j] + delta;
                if( !vis[ s2.bot[0] ][ s2.bot[1] ] ){
                    vis[ s2.bot[0] ][ s2.bot[1] ] = true;
                    pq.push( s2 );
                }
            }
    }

    for(int i = d; i >= 0; --d) if( ans[d] >= 0 ){
        printf("%d %d\n", ans[d], d);
        return;
    }
}

int main(){
    int T; scanf("%d", &T);
    while(T--){
        int a, b, c, d; scanf("%d %d %d %d", &a, &b, &c, &d);
        solve(a, b, c, d);
    }
    return 0;
}