POJ 1324 Holedox Moving(A*+状态压缩)

//
//  main.cpp
//  Richard
//
//  Created by 邵金杰 on 16/8/25.
//  Copyright © 2016年 邵金杰. All rights reserved.
//



#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
struct node{
    int x,y,s,t,f;
    bool operator < (const node &e) const {
        return f>e.f;
    }
};
struct Point{
    int x[10],y[10];
}state;
int vis[22][22][1<<15];
int n,m,l,k;
int map[25][25];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
int encode()
{
    int s=0;
    for(int i=l-1;i>0;i--)
    {
        int dir=0;
        int dirx=state.x[i]-state.x[i-1];
        int diry=state.y[i]-state.y[i-1];
        if(dirx==1&&diry==0) dir=2;
        else if(dirx==0&&diry==1) dir=1;
        else if(dirx==-1&&diry==0) dir=0;
        else if(dirx==0&&diry==-1) dir=3;
        s<<=2;s|=dir;//先腾出位置再放进去,反一反WA
    }
    return s;
}
node move(node a,int i)
{
    node p=a;
    int dir=0;
    p.x=a.x+dx[i];
    p.y=a.y+dy[i];
    int x=-dx[i],y=-dy[i];
    if(x==-1&&y==0) dir=0;
    else if(x==0&&y==1) dir=1;
    else if(x==1&&y==0) dir=2;
    else if(x==0&&y==-1) dir=3;
    p.s<<=2;
    p.s|=dir;
    p.s&=((1<<((l-1)*2))-1);
    return p;
}
Point decode(node s)
{
    Point p;
    p.x[0]=s.x;p.y[0]=s.y;
    for(int i=1;i<l;i++)
    {
        int dir=3;
        dir&=s.s;
        s.s>>=2;
        p.x[i]=p.x[i-1]+dx[dir];
        p.y[i]=p.y[i-1]+dy[dir];
    }
    return p;
}
bool judge(node e,node s)
{
    if(e.x<1||e.x>n||e.y<1||e.y>m) return false;
    if(map[e.x][e.y]==1) return false;
    if(vis[e.x][e.y][e.s]==1) return false;
    Point ss=decode(s);
    for(int i=0;i<l;i++)
        if(e.x==ss.x[i]&&e.y==ss.y[i]) return false;
    return true;
}
void Astar(node s)
{
    memset(vis,0,sizeof(vis));
    priority_queue<node> pq;
    pq.push(s);
    vis[s.x][s.y][s.s]=1;
    node e;
    while(!pq.empty())
    {
        s=pq.top();
        pq.pop();
        if(s.x==1&&s.y==1) {printf("%d\n",s.t);return ;}
        for(int i=0;i<4;i++)
        {
            e=move(s,i);
            if(!judge(e,s)) continue;
            vis[e.x][e.y][e.s]=1;
            e.t=s.t+1;
            e.f=e.t+e.x+e.y;
            pq.push(e);
        }
    }
    printf("-1\n");
}
int main()
{
    int kase=0;
    while(scanf("%d%d%d",&n,&m,&l)&&(n+m+l))
    {
        memset(map,0,sizeof(map));
        for(int i=0;i<l;i++)
            scanf("%d%d",&state.x[i],&state.y[i]);
        scanf("%d",&k);
        int x,y;
        for(int i=0;i<k;i++){
            scanf("%d%d",&x,&y);
            map[x][y]=1;
        }
        node s;
        s.x=state.x[0],s.y=state.y[0];
        s.t=0;
        s.f=s.t+s.x+s.y;
        s.s=encode();
        printf("Case %d: ",++kase);
        Astar(s);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值