1169-PIPI倒水

题目描述:
PIPI有三个杯子,容量分别为 a ,b ,c,最初只有第三个杯子有c升水,其余两个杯子都是空的,PIPI想知道至少要倒出多少升水才能够让某一个杯子中的水有 d 升,如果无法做到恰好 d 升,就让某个杯子中的水是 d’ 升,d’ 输入:
第一行包含一个正整数T,代表测试用例组数。
每一组输入四个整数 a ,b ,c, d。分别表示三个杯子的容量以及目标水量d . (1<=a,b,c,d<=200)
输出:
对于每一组输入,输出最少的倒水量和目标水量。(d或者d’)
样例输入:
2
2 3 4 2
96 97 199 62
样例输出:
2 2
9859 62

题解代码如下:

#include 
using namespace std;
const int N = 205;
bool st[N][N][N];	// 标记三个杯子中水量为i、j、k时有没有被遍历到
int res[N];			// 表示杯子里的水量与倒水总量的对应关系
int a, b, c, d;
int cup[3];			// 记录三个杯子的容量
struct Node {
    int v[3], t;	// v[0]、v[1]、v[2]表示杯子里有多少水,t表示此时总共倒了多少水
};

void bfs() {
    memset(st, 0, sizeof st);
    memset(res, -1, sizeof res);
    
    queue<Node> q;
    Node node;
    node.v[0] = 0, node.v[1] = 0, node.v[2] = cup[2], node.t = 0;
    st[0][0][cup[2]] = true;
    q.push(node);
    
    while (q.size()) {
        auto now = q.front(); q.pop();
        // 如果当前水量没有对应的t则更新t
        for (int i = 0; i < 3; i ++ ) {
            if (res[now.v[i]] == -1) res[now.v[i]] = now.t;
        }
        
        if (res[d] != -1) break;
        
        // 第i个杯子和第j个杯子相互倒水
        for (int i = 0; i < 3; i ++ ) {
            for (int j = 0; j < 3; j ++ ) {
                if (i == j) continue;
                // 如果第i个杯子为空或者第j个杯子是满的则跳过
                if (now.v[i] == 0 || now.v[j] == cup[j]) continue;
                // 取第i个杯子的总水量和第j个杯子剩下的水量的最小值
                int pour = min(now.v[i], cup[j] - now.v[j]);
                Node next = now;
                // 将水量加入总和中
                next.t += pour;
                // 第i个杯子倒出pour升水,第j个杯子倒入pour升水
                next.v[i] -= pour, next.v[j] += pour;
                // 查看下个状态是否被访问,如果被访问则标记
                if (!st[next.v[0]][next.v[1]][next.v[2]]) {
                    st[next.v[0]][next.v[1]][next.v[2]] = true;
                    q.push(next);
                }
            }
        }
    }
    
    // 从大到小输出答案
    while (d >= 0) {
        if (res[d] != -1) {
            printf("%d %d\n", res[d], d);
            break;
        }
        d -- ;
    }
}
int main() {
    int n;
    cin >> n;
    while (n -- ) {
        cin >> a >> b >> c >> d;
        cup[0] = a, cup[1] = b, cup[2] = c;
        bfs();
    }
    
    return 0;
}

你可能感兴趣的:(PIPIOJ,算法,bfs)