题目链接:http://www.pipioj.online/problem.php?id=1169

题目大意:PIPI有三个杯子,容量分别为 a ,b ,c,最初只有第三个杯子有c升水,其余两个杯子都是空的,PIPI想知道至少要倒出多少升水才能够让某一个杯子中的水有 d 升,如果无法做到恰好 d 升,就让某个杯子中的水是 d' 升,d'<d且尽可能接近 d。(由于杯子没刻度,所以我们一个杯子往另一个杯子倒水时,要么将倒出的杯子的水倒空,要么将倒入的杯子倒满)

#include<bits/stdc++.h>
using namespace std;
const int N=206;
struct node{
    int v[3],d;//状态定义为三只瓶子里装的水量,以及已经倒了多少水量 
    bool operator<(const node &te)const{
    return d>te.d;//注意细节return 
    }
};//要使得到达目标状态时的倒水量d尽可能少,故采用优先队列 
bool vis[N][N];//三瓶水的总水量是固定的,二维数组即可 
int cap[3],d,ans[N];//ans[i]表示的是使得三个杯子中的任意一个杯子刚好为i升水所需的总水量 

void bfs(){
    priority_queue<node>q;
    memset(vis,0,sizeof(vis));
    memset(ans,-1,sizeof(ans));
    q.push({0,0,cap[2],0});
    vis[0][0]=1;
    while(q.size()){
        node now=q.top();q.pop();
        printf("%d %d %d %d\n",now.v[0],now.v[1],now.v[2],now.d);
        for(int i=0;i<3;i++){
            if(ans[now.v[i]]==-1) ans[now.v[i]]=now.d;
        }
        if(ans[d]!=-1) break;//如果恰有某只瓶子里的水量为d
        for(int i=0;i<3;i++){//第i只桶向第j只桶里倒水 
            for(int j=0;j<3;j++){
                if(i==j) continue;
                if(now.v[i]==0||now.v[j]==cap[j]) continue;
                int pour=min(now.v[i],cap[j]-now.v[j]); //要么把水倒光,要么把桶水装满 
                node next=now;
                 next.v[i]-=pour,next.v[j]+=pour;
                 if(vis[next.v[0]][next.v[1]]) continue;
                 vis[next.v[0]][next.v[1]]=1;
                 next.d+=pour;
                 q.push(next);
            }
        }    
    }
    while(d>=0){
        if(ans[d]>=0){
            printf("%d %d\n",ans[d],d);
            break;
        }
        d--;
    }
    return; 
}
int main() {
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d%d%d",&cap[0],&cap[1],&cap[2],&d);
        bfs();
    }
}