题目链接: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(); } }