poj 1324 Holedox Moving 宽搜

一道搜索的题目,用了状态压缩,把 蛇的身体后面的部分与前一部分的相对位置存储起来,加上头的位置。共有20*20*4^7个状态
然后就是广搜的过程了,先压缩,进队列,解压,然后拓展节点。遇到终点退出。
#include
#include
#include
using namespace std;
const int inf=99999999;
int n,m,l;
int ans[21][21][17000];
int a[21][21];
int x[10],y[10];

struct
{
    int t,s,tmp;
}que[1000001];

int bfs()
{
    memset(ans,111,sizeof(ans));
    int front=1,end=1;
    que[1].t=x[1];
    que[1].s=y[1];
    int tmp=0,txt=1;
    for(int i=2;i<=l;i++)
    {
        int ted;
        if(x[i]+1==x[i-1]) ted=0;
        else if(x[i]-1==x[i-1]) ted=1;
        else if(y[i]+1==y[i-1]) ted=2;
        else ted=3;
        tmp+=ted*txt;
        txt<<=2;
    }

//     printf("%d\n",tmp);

    que[1].tmp=tmp;
    ans[x[1]][y[1]][tmp]=0;
    while(front<=end)
    {
        int t=que[front].t,s=que[front].s,tmp=que[front].tmp;
        if(t==1&&s==1) break;
        front++;
        int tt=tmp;
        int t1=t,s1=s;
        for(int i=2;i<=l;i++)
        {
            int ted=tt%4;
            tt/=4;
            if(ted==0) t1--;
            else if(ted==1) t1++;
            else if(ted==2) s1--;
            else s1++;
            a[t1][s1]++;
        }
        tt=tmp;
        int mm=(1<<((l-2)*2))-1;
        tt&=mm;
        tt<<=2;

        if(t+1<=n&&a[t+1][s]==0)
        {
            if(ans[t+1][s][tt]>ans[t][s][tmp]+1)
            {
                que[++end].t=t+1;
                que[end].s=s;
                que[end].tmp=tt;
                ans[t+1][s][tt]=ans[t][s][tmp]+1;
            }
        }
        if(t-1>=1&&a[t-1][s]==0)
        {
            if(ans[t-1][s][tt+1]>ans[t][s][tmp]+1)
            {
                que[++end].t=t-1;
                que[end].s=s;
                que[end].tmp=tt+1;
                ans[t-1][s][tt+1]=ans[t][s][tmp]+1;
            }
        }
        if(s+1<=m&&a[t][s+1]==0)
        {
            if(ans[t][s+1][tt+2]>ans[t][s][tmp]+1)
            {
                ans[t][s+1][tt+2]=ans[t][s][tmp]+1;
                que[++end].t=t;
                que[end].s=s+1;
                que[end].tmp=tt+2;
            }
        }
        if(s-1>=1&&a[t][s-1]==0)
        {
            if(ans[t][s-1][tt+3]>ans[t][s][tmp]+1)
            {
                ans[t][s-1][tt+3]=ans[t][s][tmp]+1;
                que[++end].t=t;
                que[end].s=s-1;
                que[end].tmp=tt+3;
            }
        }
        tt=tmp;
        t1=t,s1=s;
        for(int i=2;i<=l;i++)
        {
            int ted=tt%4;
            tt>>=2;
            if(ted==0) t1--;
            else if(ted==1) t1++;
            else if(ted==2) s1--;
            else s1++;
            a[t1][s1]--;
        }
    }
}


int main()
{
    int time=0;
    while(scanf("%d %d %d",&n,&m,&l),n&&m&&l)
    {
        time++;
        memset(a,0,sizeof(a));
        for(int i=1;i<=l;i++)
        scanf("%d %d",&x[i],&y[i]);
        {
            int k;
            scanf("%d",&k);
            for(int i=1;i<=k;i++)
            {
                int x,y;
                scanf("%d %d",&x,&y);
                a[x][y]=1;
            }
        }
        bfs();
        int answer=inf;
        for(int i=0;i<=16500;i++)
        if(answer>ans[1][1][i])
        answer=ans[1][1][i];
        if(answer!=inf)
        printf("Case %d: %d\n",time,answer);
        else
        printf("Case %d: -1\n",time);

    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值