倒水问题,求可以倒出最接近要求的水量和倒出的总水量,如果相差最小的时候有两个解,取较小的那一个
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
int val[3],goal;
int xiao,indx;
int end,pour,mincha;
int vis[200][200][200]; //相应状态下最少的倒水量
struct node{
int cup[3];
int sum;
}state;
queue<node> q;
int cha(int a)
{
if(a>goal)
return a-goal;
else
return goal-a;
}
int chamin(node* p) //p状态中最接近目标的cup与goal的差
{
int i;
int v[3];
for(i=0;i<3;i++)
v[i]=cha(p->cup[i]);
sort(v,v+3);
for(i=0;i<3;i++)
if(v[0]==cha(p->cup[i]))
indx=i; //最接近的下标
return v[0];
}
void judge(node p)
{
int i,j,k;
i=p.cup[0];
j=p.cup[1];
k=p.cup[2];
if(vis[i][j][k]==-1)
{
int v=chamin(&p);
if(v==mincha)
{
if(p.cup[indx]==end)
{
if(pour>p.sum)
pour=p.sum;
}
if(p.cup[indx]<goal&&xiao==0)
{
end=p.cup[indx];
pour=p.sum;
xiao=1;
}
q.push(p);
vis[i][j][k]=p.sum;
}
else if(v<mincha)
{
mincha=v;
end=p.cup[indx];
pour=p.sum;
if(p.cup[indx]>goal)
xiao=0;
else
xiao=1;
q.push(p);
vis[i][j][k]=p.sum;
}
else if(v>mincha)
{
vis[i][j][k]=p.sum;
q.push(p);
vis[i][j][k]=p.sum;
}
}
else if(p.sum < vis[i][j][k])
{
vis[i][j][k]=p.sum;
q.push(p);
}
}
void bfs()
{
int i,j;
node p;
p.cup[0]=0;
p.cup[1]=0;
p.cup[2]=val[2];
p.sum=0;
vis[p.cup[0]][p.cup[1]][p.cup[2]]=0;
if(chamin(&p)<mincha)
{
mincha=chamin(&p);
end=p.cup[2];
pour=p.sum;
if(p.cup[2]-goal<0)
xiao=1;
else
xiao=0;
}
q.push(p);
while(!q.empty())
{
p=q.front();
q.pop();
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
if(i==j)
continue;
node t=p;
if( p.cup[i] >0 && val[j] - p.cup[j]>0) //i可向j中倒水
{
int c= p.cup[i] - (val[j] - p.cup[j]);
if(c>=0) //倒完i中还剩水
{
t.cup[j]=val[j];
t.cup[i]=c;
t.sum=p.sum+p.cup[i]-c;
}
else
{
t.cup[j]=p.cup[j]+p.cup[i];
t.cup[i]=0;
t.sum=p.sum+p.cup[i];
}
judge(t);
}
}
}
}
}
int main()
{
int i,j,k,l,m,n;
scanf("%d",&n);
while(n--)
{
memset(vis,-1,sizeof(vis));mincha=9999999;
xiao=1;//xiao是1 就是当前end值要比goal小等于 用此取多解时的较小数
scanf("%d %d %d %d",&val[0],&val[1],&val[2],&goal);
bfs();
printf("%d %d\n",pour,end);
}
return 0;
}
364

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



