HDU 1813 Escape from Tetris (IDA*)

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1813

 

题意:给你一个n*n的迷宫,其中0代表有一个人在这个位置,1代表墙,现在要求一个路线,使所有的人通过这个路线都可以走到迷宫的边界

注意当到达边界就相当于出去了不用继续走了,一个格子可以容纳很多人。

题解:先用BFS求出迷宫内部的点走到边界的最小步数(为了后面的IDA*剪枝),因为有很多状态,不好表示,所以可以想到用IDA*算法,在dfs的时候每次内部的点安同一个方向走,当某个点走到边界或遇见墙时不变,其他的点还是继续走。

 

AC代码:

#include <iostream>

#include <cstdio>

#include <cstring>

#include <string>

#include <cstdlib>

#include <cmath>

#include <vector>

#include <list>

#include <deque>

#include <queue>

#include <iterator>

#include <stack>

#include <map>

#include <set>

#include <algorithm>

#include <cctype>

using namespace std;



#define si1(a) scanf("%d",&a)

#define si2(a,b) scanf("%d%d",&a,&b)

#define sd1(a) scanf("%lf",&a)

#define sd2(a,b) scanf("%lf%lf",&a,&b)

#define ss1(s)  scanf("%s",s)

#define pi1(a)    printf("%d\n",a)

#define pi2(a,b)  printf("%d %d\n",a,b)

#define mset(a,b)   memset(a,b,sizeof(a))

#define forb(i,a,b)   for(int i=a;i<b;i++)

#define ford(i,a,b)   for(int i=a;i<=b;i++)



typedef long long LL;

const int N=11;

const int INF=0x3f3f3f3f;

const double PI=acos(-1.0);

const double eps=1e-7;



int n,depth;

int cnt;//表示不是边界点的个数

int x[101],y[101];//存放不是边界的点

int xh[N][N];//xh[i][j]表示ij到边界的最短距离,由BFS生成

char str[N][N];

int ans[1000];//存放方向

int dir[4][2]={0,1,-1,0,1,0,0,-1};//east north south west 按照字典序

bool flag;



struct node

{

    int x,y;

}w,e;



bool bianjie(int x,int y)

{

    if(x==0||x==n-1||y==0||y==n-1)

        return true;

    return false;

}



bool inmap(int x,int y)

{

    if(x>=0&&x<n&&y>=0&&y<n)

        return true;

    return false;

}



void bfs()

{

    queue<node> q;

    q.push(w);

    xh[w.x][w.y]=0;

    while(!q.empty())

    {

        e=q.front();

        q.pop();



        for(int i=0;i<4;i++)

        {

            w.x=e.x+dir[i][0];

            w.y=e.y+dir[i][1];

            if(inmap(w.x,w.y)&&str[w.x][w.y]=='0')

            {

                if(xh[w.x][w.y]<=xh[e.x][e.y]) continue;

                xh[w.x][w.y]=xh[e.x][e.y]+1;

                q.push(w);

            }

        }

    }

}



int geth(int x[],int y[])//统计最大的距离

{

    int ss=0;

    forb(i,0,cnt)   ss=max(ss,xh[x[i]][y[i]]);

    return ss;

}



void dfs(int tx[],int ty[],int de)

{

    if(flag)    return ;

    if(geth(tx,ty)>de)  return ;

    if(de==0)//或者geth(tx,ty)==0

    {

        flag=true;

        return ;

    }

    for(int i=0;i<4;i++)

    {

        int xx[101],yy[101];

        for(int j=0;j<cnt;j++)//不是边界的点都按照i这个方向走

        {

            xx[j]=tx[j];    yy[j]=ty[j];

            if(bianjie(xx[j],yy[j]))    continue;

            if(str[xx[j]+dir[i][0]][yy[j]+dir[i][1]]=='0')

            {

                xx[j]+=dir[i][0];

                yy[j]+=dir[i][1];

            }

        }

        ans[de]=i;

        dfs(xx,yy,de-1);

        if(flag)    return;//这个地方一定要加上这一句,不然会被覆盖

    }

}



void IDA()

{

    flag=false;

    depth=geth(x,y);

    while(1)

    {

        dfs(x,y,depth);

        if(flag)

        {

            for(int i=depth;i>0;i--)

            {

                if(ans[i]==0)   puts("east");

                if(ans[i]==1)   puts("north");

                if(ans[i]==2)   puts("south");

                if(ans[i]==3)   puts("west");

            }

            break;

        }

        depth++;

    }

}



int main()

{

//    freopen("input.txt","r",stdin);

    int ca=0;

    while(~si1(n))

    {

        forb(i,0,n) ss1(str[i]);

        mset(xh,INF);//初始化为无穷大

        cnt=0;

        forb(i,0,n)

            forb(j,0,n)

                if(str[i][j]=='0')

                {

                    w.x=i;  w.y=j;

                    if(!bianjie(i,j))

                    {

                        x[cnt]=i;

                        y[cnt]=j;

                        cnt++;

                    }

                    else

                        bfs();//求出每个点要走出去的最小步数

                }

        if(ca++)    printf("\n");

        if(cnt==0||geth(x,y)==INF)  {continue;}//都是边界点|走不出去的情况



        IDA();

    }

    return 0 ;

}


 

 

你可能感兴趣的:(escape)