/*白书上有讲解,实现的时候注意细节地方的处理。
倒水的代码是重复的。隐式图的BFS应用。
题意是输出到达d或最接近d的值d'时的总倒水量以及d或d'
注意用vis数组记录已经访问过的状态,由于是BFS搜索,所以每个状态
记录的都是其最小倒水量*/
#include<stdio.h>
#include<string.h>
#define ATOB 1
#define ATOC 2
#define BTOA 3
#define BTOC 4
#define CTOA 5
#define CTOB 6
int a,b,c,d,sum,des;
typedef struct node{
int a,b,c;
int sum;
}S;
S queue[10010];
int vis[202][202][202],rear,front;
int PourWater(S from,S &dest,int status)
{
int na,nb,nc;
switch(status)
{
case ATOB:
if(from.a>0)
{
if((from.a+from.b)<=b)
{
na=dest.a=0;
nb=dest.b=from.b+from.a;
nc=dest.c=from.c;
dest.sum=from.sum+from.a;
if(!vis[na][nb][nc]){vis[na][nb][nc]=1;return 1;}
else return 0;
}
else
{
na=dest.a=from.a+from.b-b;
nb=dest.b=b;
nc=dest.c=from.c;
dest.sum=from.sum+b-from.b;
if(!vis[na][nb][nc]){vis[na][nb][nc]=1;return 1;}
else return 0;
}
}
return 0;
break;
case ATOC:
if(from.a>0)
{
if((from.a+from.c)<=c)
{
na=dest.a=0;
nb=dest.b=from.b;
nc=dest.c=from.c+from.a;
dest.sum=from.sum+from.a;
if(!vis[na][nb][nc]){vis[na][nb][nc]=1;return 1;}
else return 0;
}
else
{
na=dest.a=from.a+from.c-c;
nb=dest.b=from.b;
nc=dest.c=c;
dest.sum=from.sum+c-from.c;
if(!vis[na][nb][nc]){vis[na][nb][nc]=1;return 1;}
else return 0;
}
}
return 0;
break;
case BTOA:
if(from.b>0)
{
if((from.b+from.a)<=a)
{
nb=dest.b=0;
na=dest.a=from.a+from.b;
nc=dest.c=from.c;
dest.sum=from.sum+from.b;
if(!vis[na][nb][nc]){vis[na][nb][nc]=1;return 1;}
else return 0;
}
else
{
nb=dest.b=from.b+from.a-a;
na=dest.a=a;
nc=dest.c=from.c;
dest.sum=from.sum+a-from.a;
if(!vis[na][nb][nc]){vis[na][nb][nc]=1;return 1;}
else return 0;
}
}
return 0;
break;
case BTOC:
if(from.b>0)
{
if((from.b+from.c)<=c)
{
na=dest.a=from.a;
nb=dest.b=0;
nc=dest.c=from.c+from.b;
dest.sum=from.sum+from.b;
if(!vis[na][nb][nc]){vis[na][nb][nc]=1;return 1;}
else return 0;
}
else
{
na=dest.a=from.a;
nb=dest.b=from.b+from.c-c;
nc=dest.c=c;
dest.sum=from.sum+c-from.c;
if(!vis[na][nb][nc]){vis[na][nb][nc]=1;return 1;}
else return 0;
}
}
return 0;
break;
case CTOA:
if(from.c>0)
{
if((from.c+from.a)<=a)
{
nc=dest.c=0;
nb=dest.b=from.b;
na=dest.a=from.a+from.c;
dest.sum=from.sum+from.c;
if(!vis[na][nb][nc]){vis[na][nb][nc]=1;return 1;}
else return 0;
}
else
{
nc=dest.c=from.c+from.a-a;
na=dest.a=a;
nb=dest.b=from.b;
dest.sum=from.sum+a-from.a;
if(!vis[na][nb][nc]){vis[na][nb][nc]=1;return 1;}
else return 0;
}
}
return 0;
break;
case CTOB:
if(from.c>0)
{
if((from.c+from.b)<=b)
{
nc=dest.c=0;
na=dest.a=from.a;
nb=dest.b=from.b+from.c;
dest.sum=from.sum+from.c;
if(!vis[na][nb][nc]){vis[na][nb][nc]=1;return 1;}
else return 0;
}
else
{
nc=dest.c=from.c+from.b-b;
nb=dest.b=b;
na=dest.a=from.a;
dest.sum=from.sum+b-from.b;
if(!vis[na][nb][nc]){vis[na][nb][nc]=1;return 1;}
else return 0;
}
}
return 0;
break;
}
return 0;
}
void AcquireDistance(S ok)
{
int temp=des,t;
t=d-ok.a;
if(t>=0&&t<=temp)temp=t;
t=d-ok.b;
if(t>=0&&t<=temp)temp=t;
t=d-ok.c;
if(t>=0&&t<=temp)temp=t;
if(temp<des)
{
sum=ok.sum;
des=temp;
}
if(temp==des&&ok.sum<sum)sum=ok.sum;
}
int BFS()
{
int i;
S state,oldstate,newstate;
rear=front=0;
state.a=0;
state.b=0;
state.c=c;
state.sum=0;
queue[rear++]=state;
vis[0][0][c]=1;
while(front!=rear)
{
oldstate=queue[front++];
front%=10000;
for(i=1;i<=6;i++)
{
if(PourWater(oldstate,newstate,i))
{
AcquireDistance(newstate);
queue[rear++]=newstate;
}
}
rear%=10000;
}
}
int main()
{
int T,i,j,k;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
des=sum=2147483647;
memset(vis,0,sizeof(vis));
if(c<=d||(a>=c&&b>=c)){printf("0 %d\n",c);continue;}
BFS();
printf("%d %d\n",sum,d-des);
}
return 0;
}
UVA - 10603 - Fill
最新推荐文章于 2019-09-15 17:31:02 发布