UVA - 10603 - Fill

/*白书上有讲解,实现的时候注意细节地方的处理。
倒水的代码是重复的。隐式图的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;
}        


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值