hdu4634 搜索+状态压缩

很好的搜索,写起来条件考虑很多很繁琐,交上去各种自挂东南枝,最后写了个数据生成与标称对拍查错,搞了2小时总算AC了。


ACcode:

#include<cstdio>
#include<cstring>
#include<algorithm>
using std::min;

const int NS=222;
const int MS=9;
const int INF=0x3f3f3f3f;

struct node{
    int x,y,st;
    node(){}
    node(int tx,int ty,int tst):
        x(tx),y(ty),st(tst){}
}que[1<<15];

int n,m;
int edx,edy,top;
char ch[NS][NS];
int px[MS],py[MS];
int dis[MS][4][MS][4];
int f[NS][NS][4];
int dp[1<<MS][MS][4];
int trans[NS];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};

void init()
{
    trans['U']=0,trans['R']=1,trans['D']=2,
    trans['L']=3,trans['.']=4,trans['S']=4;
    trans['K']=4,trans['E']=4,trans['#']=9;
}

int boundary(int x,int y)
{
    if (x<0||x>=n) return 0;
    if (y<0||y>=m) return 0;
    return 1;
}

void bfs(int x,int y,int dir)
{
    memset(f,0x3f,sizeof(f));
    int cx=x+dx[dir];
    int cy=y+dy[dir];
    int st=0,lft=0,rgt=0;
    f[x][y][dir]=0;
    if ( !boundary(cx,cy) || ch[cx][cy]=='#' ) return ;

    int tx=cx,ty=cy;
    while ( boundary(tx,ty) && ch[tx][ty]!='#' && f[tx][ty][dir]>st)
    {
        f[tx][ty][dir]=st;
        if (trans[ch[tx][ty]]<4)
        {
            dir=trans[ch[tx][ty]];
            f[tx][ty][dir]=st;
        }
        tx+=dx[dir],ty+=dy[dir];
    }
    if (!boundary(tx,ty) || ch[tx][ty]!='#') return ;
    tx-=dx[dir],ty-=dy[dir];
    if (ch[tx][ty]=='.')
    que[rgt++]=node(tx,ty,st);

    while (lft<rgt)
    {
        cx=que[lft].x;
        cy=que[lft].y;
        st=que[lft++].st+1;

        for (int i=0;i<4;i++)
        {
            dir=i;
            tx=cx+dx[i];
            ty=cy+dy[i];
            f[cx][cy][dir]=min(st,f[cx][cy][dir]);
            if ( !boundary(tx,ty) || ch[tx][ty]=='#' || f[tx][ty][dir]<=st) continue;

            while ( boundary(tx,ty) && ch[tx][ty]!='#' && f[tx][ty][dir]>st)
            {
                f[tx][ty][dir]=st;
                int tmp=trans[ch[tx][ty]];
                if (tmp<4)
                {
                    dir=tmp;
                    f[tx][ty][dir]=st;
                }
                tx+=dx[dir],ty+=dy[dir];
            }
            if (!boundary(tx,ty) || ch[tx][ty]!='#') continue;
            tx-=dx[dir],ty-=dy[dir];
            if (ch[tx][ty]=='.')
            que[rgt++]=node(tx,ty,st);
        }
    }
}

int main()
{
    init();
    while (~scanf("%d %d",&n,&m))
    {
        top=1;
        for (int i=0;i<n;i++)
        {
            scanf("%s",ch[i]);
            for (int j=0;j<m;j++)
            {
                char tmp=ch[i][j];
                if (tmp=='K')
                    px[top]=i,py[top++]=j;
                if (tmp=='S')
                    px[0]=i,py[0]=j;
                if (tmp=='E')
                    edx=i,edy=j;
                if( trans[tmp]==4)
                    ch[i][j]='.';
            }
        }
        px[top]=edx,py[top]=edy;

        for (int i=0;i<top;i++)
        for (int j=0;j<4;j++)
        {
            bfs(px[i],py[i],j);
            for (int ei=0;ei<=top;ei++)
            for (int ej=0;ej<4;ej++)
            dis[i][j][ei][ej]=f[px[ei]][py[ei]][ej];

        }
        int lim=1<<(top+1);
        memset(dp,0x3f,sizeof(dp));
        for (int i=0;i<4;i++)
        dp[1][0][i]=1;
        for (int i=3;i<lim;i+=2)
        for (int j=1;j<=top;j++)
        if (i&(1<<j))
        {
            int sta=i^(1<<j);
            for (int d=0;d<4;d++)
            for (int a=0;a<top;a++)
            if (sta&(1<<a))
            {
                for (int b=0;b<4;b++)
                dp[i][j][d]=min(dp[i][j][d],dp[sta][a][b]+dis[a][b][j][d]);
            }
        }
        int ans=INF;
        for (int i=0;i<4;i++)
            ans=min(ans,dp[lim-1][top][i]);
        if (ans>=INF) ans=-1;
        printf("%d\n",ans);
    }
    return 0;
}
/*
1 5
SEK.#

1 4
SEK#

1 3
SE#

1 5
SE.#K

4 4
.#L#
.RS#
.RKE
#DUD

4 4
####
#K.D
#DS#
#ELD
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值