Fill UVA - 10603
图论·最短路
题目大意:
有3个没有刻度的水壶,容量分别为a,b,c(均不超过200的正整数)。初始时候前两个水壶空,第三个装满了水。每次可以从一个水壶往另一个水壶倒水,直到其中一个水壶倒空或者另一个水壶倒满。为了使某个水壶恰好有d升水,至少要倒多少升的水?如果无解,则找一个小于且最接近于d的d’代替。
输出要求输出至少倒多少升水 和 d(d’)
题解:
优先队列+bfs即可。
Code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int N = 201;
const int INF = 0x3f3f3f3f;
int mn[N*3],f,d[3];
struct Node{
int state[3];
int val;
Node(){}
Node(int a,int b,int c,int v){ state[0]=a; state[1]=b; state[2]=c; val=v; }
bool operator < (const Node &tp) const {
return val > tp.val;
}
};
bool vis[N][N][N];
void bfs(){
memset(vis,0,sizeof(vis));
priority_queue<Node> q;
q.push(Node(0,0,d[2],0));
while(!q.empty()){
Node x=q.top(); q.pop();
for(int i=0;i<3;i++){
mn[x.state[i]]=min(mn[x.state[i]],x.val);
}
if(mn[f]!=INF) return;
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if(i==j) continue;
int flow=min(x.state[i],d[j]-x.state[j]);
Node y; y.val=x.val+flow;
for(int k=0;k<3;k++){
int tp=x.state[k];
if(k==i) tp-=flow;
if(k==j) tp+=flow;
y.state[k]=tp;
}
if(!vis[y.state[0]][y.state[1]][y.state[2]]){
vis[y.state[0]][y.state[1]][y.state[2]]=true;
q.push(y);
}
}
}
}
}
int main(){
freopen("a.in","r",stdin);
int T; cin>>T;
while(T--){
memset(mn,0x3f,sizeof(mn));
scanf("%d%d%d%d",&d[0],&d[1],&d[2],&f);
bfs();
while(mn[f]==INF) f--;
printf("%d %d\n",mn[f],f);
}
}