题意:你有三个无刻度的杯子A,B,C,容量分别是a,b,c。C中装满水,A和B是空杯。你需要借助三个杯子量出体积为d的水,如果无法量出d,量d'使得d'<d并尽可能接近d。输出你能实际量出的水量和最小的倒水体积。
思路:BFS,其实也就是原状态与目标状态的最短路,目标状态可以有许多,在BFS的过程中判断当前状态是不是更好的状态,把最好的状态作为目标状态。我是用SPFA写的,重复的代码有点多看着比较挫,就像紫书说的一样,搜索和图论是存在一定联系的。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <ctype.h>
#define INF 1000000010
#define ll long long
#define max3(a,b,c) max(a,max(b,c))
#define MAXN 1000
using namespace std;
int dis[40410];
inline int hash(int a,int b){
return a*201+b;
}
inline void dehash(int n,int& x,int& y){
y=n%201;
n/=201;
x=n;
}
int main(){
int t;
cin>>t;
while(t--){
for(int i=0;i<40410;i++)dis[i]=INF;
int a,b,c,d;
cin>>a>>b>>c>>d;
int s=hash(0,0);
dis[s]=0;
queue<int> que; que.push(s);
int _max;
if(c<=d){
_max=c;
}else{
_max=0;
}
int ans=0;
while(!que.empty()){
int cur=que.front(); que.pop();
int x,y,z;
dehash(cur,x,y);
z=c-x-y;
int nx,ny,nz;
if(x>0&&y<b){
int v=min(x,b-y);
nx=x-v; ny=y+v; nz=z;
if(dis[cur]+v<dis[ hash(nx,ny) ] ){
que.push(hash(nx,ny));
dis[ hash(nx,ny) ]=dis[cur]+v;
//
if( (nx>_max&&nx<=d) || (nx==_max&&dis[cur]+v<ans) ){
_max=nx;
ans=dis[cur]+v;
}
if( (ny>_max&&ny<=d) || (ny==_max&&dis[cur]+v<ans) ){
_max=ny;
ans=dis[cur]+v;
}
}
}
if(x>0&&z<c){
int v=min(x,c-z);
nx=x-v; ny=y; nz=z+v;
if(dis[cur]+v<dis[ hash(nx,ny) ] ){
que.push(hash(nx,ny));
dis[ hash(nx,ny) ]=dis[cur]+v;
//
if( (nx>_max&&nx<=d) || (nx==_max&&dis[cur]+v<ans) ){
_max=nx;
ans=dis[cur]+v;
}
if( (nz>_max&&nz<=d) || (nz==_max&&dis[cur]+v<ans) ){
_max=nz;
ans=dis[cur]+v;
}
}
}
if(y>0&&x<a){
int v=min(y,a-x);
nx=x+v; ny=y-v; nz=z;
if(dis[cur]+v<dis[ hash(nx,ny) ] ){
que.push(hash(nx,ny));
dis[ hash(nx,ny) ]=dis[cur]+v;
//
if( (nx>_max&&nx<=d) || (nx==_max&&dis[cur]+v<ans) ){
_max=nx;
ans=dis[cur]+v;
}
if( (ny>_max&&ny<=d) || (ny==_max&&dis[cur]+v<ans) ){
_max=ny;
ans=dis[cur]+v;
}
}
}
if(y>0&&z<c){
int v=min(y,c-z);
nx=x; ny=y-v; nz=z+v;
if(dis[cur]+v<dis[ hash(nx,ny) ] ){
que.push(hash(nx,ny));
dis[ hash(nx,ny) ]=dis[cur]+v;
//
if( (ny>_max&&ny<=d) || (ny==_max&&dis[cur]+v<ans) ){
_max=ny;
ans=dis[cur]+v;
}
if( (nz>_max&&nz<=d) || (nz==_max&&dis[cur]+v<ans) ){
_max=nz;
ans=dis[cur]+v;
}
}
}
if(z>0&&x<a){
int v=min(z,a-x);
nx=x+v; ny=y; nz=z-v;
if(dis[cur]+v<dis[ hash(nx,ny) ] ){
que.push(hash(nx,ny));
dis[ hash(nx,ny) ]=dis[cur]+v;
//
if( (nx>_max&&nx<=d) || (nx==_max&&dis[cur]+v<ans) ){
_max=nx;
ans=dis[cur]+v;
}
if( (nz>_max&&nz<=d) || (nz==_max&&dis[cur]+v<ans) ){
_max=nz;
ans=dis[cur]+v;
}
}
}
if(z>0&&y<b){
int v=min(z,b-y);
nx=x; ny=y+v; nz=z-v;
if(dis[cur]+v<dis[ hash(nx,ny) ] ){
que.push(hash(nx,ny));
dis[ hash(nx,ny) ]=dis[cur]+v;
//
if( (ny>_max&&ny<=d) || (ny==_max&&dis[cur]+v<ans) ){
_max=ny;
ans=dis[cur]+v;
}
if( (nz>_max&&nz<=d) || (nz==_max&&dis[cur]+v<ans) ){
_max=nz;
ans=dis[cur]+v;
}
}
}
}
cout<<ans<<" "<<_max<<endl;
}
return 0;
}