#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
const int maxn=200+10;
int t,A,B,C,D,max1,ans;
int vis[maxn][maxn],tol[4];//tol数组用来记录三个容器的体积,vis用来记录第一个和第二个容器状态是否访问过,当第一第二确定时第三个状态也是确定的,二维即可
struct P
{
int v[4],val;
P(int a,int b,int c,int d)
{
v[0]=a;
v[1]=b;
v[2]=c;
val=d;
}
bool operator < (const P &a) const
{
return val>a.val;
}
};
void BFS(int a,int b,int c,int d)
{
priority_queue<P> qu;
P p(0,0,c,0);
qu.push(p);
vis[0][0]=1;
while(!qu.empty())
{
P q=qu.top();
if(q.v[0]==d || q.v[1]==d || q.v[2]==d)//能倒出来目标状态就退出
{
ans=q.val;
max1=d;
break;
}
else//此处寻找不满足目标时的最佳状态
for(int i=0; i<3; i++)
if(q.v[i] && q.v[i]<d)
{
if(q.v[i]>max1)
{
max1=max(max1,q.v[i]);
ans=q.val;
}
}
qu.pop();
for(int i=0; i<3; i++)
{
for(int j=0; j<3; j++)
{
if(i!=j)
{
if(q.v[i]!=0 && q.v[j]<tol[j])//只要i不是空的,j不满,就可以进行倒水操作
{
P tem=q;
if(q.v[i]>=(tol[j]-q.v[j]))//如果能把j倒满
{
tem.v[i]=q.v[i]-(tol[j]-q.v[j]);
tem.v[j]=tol[j];
tem.val=q.val+tol[j]-q.v[j];
}
else//如果不能把j倒满
{
tem.v[i]=0;
tem.v[j]=q.v[j]+q.v[i];
tem.val=q.v[i]+q.val;
}
if(!vis[tem.v[0]][tem.v[1]])
{
qu.push(tem);
vis[tem.v[0]][tem.v[1]]=1;
}
}
}
}
}
}
printf("%d %d\n",ans,max1);
}
int main()
{
scanf("%d",&t);
while(t--)
{
memset(vis,0,sizeof(vis));
max1=0;
ans=0;
scanf("%d%d%d%d",&A,&B,&C,&D);
tol[0]=A;
tol[1]=B;
tol[2]=C;
BFS(A,B,C,D);
}
return 0;
}刘汝佳的代码确实没看懂,我这样写可以理解为只是个bfs罢了,重点在于状态拓展用bfs搜索。

967

被折叠的 条评论
为什么被折叠?



