【搜索进阶】HDU 1813 Escape from Tetris

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1813
IDA*:求出某个位置逃出的最少步数,然后在构造 h() 为所有点逃离迷宫的最少步数的最大值
#include<cstdio>
#include<cstring>
using namespace std;
int n;
bool maze[10][10];
int dir[4][2]={{0,1},{-1,0},{1,0},{0,-1}}; 
int ans[100];
int dis[10][10];
int deep; 
struct S{
    bool maze[10][10];
    S(){memset(maze,false,sizeof(maze));}
}s; 
inline bool h(int d,S ts){
    for(int i=1;i<n-1;i++){
        for(int j=1;j<n-1;j++){
            if(!ts.maze[i][j]) continue;
            if(dis[i][j]+d>deep){
                return false;
            }
        }
    }
    return true;
} 
bool dfs(int d,S tu){
    if(!h(d,tu)) return false;
    if(d==deep) return true;
    for(int i=0;i<4;i++){
        S tv;
        for(int ii=1;ii<n-1;ii++){
            for(int jj=1;jj<n-1;jj++){
                if(!maze[ii][jj]) continue;
                int tx=ii-dir[i][0];
                int ty=jj-dir[i][1];
                tv.maze[ii][jj]=tu.maze[tx][ty];
                tx=ii+dir[i][0];
                ty=jj+dir[i][1];
                if(maze[tx][ty]) continue;
                tv.maze[ii][jj]|=tu.maze[ii][jj];
            }
        }
        ans[d]=i;
        if(dfs(d+1,tv)) return true;
    }
    return false;
} 
int que[1000][2];
void bfs(int x,int y){
    dis[x][y]=0;
    int ss=0,ee=0;
    que[0][0]=x;
    que[0][1]=y;
    while(ss<=ee){
        int ux=que[ss][0];
        int uy=que[ss][1];
        ss++;
        for(int i=0;i<4;i++){
            int tx=ux+dir[i][0];
            int ty=uy+dir[i][1];
            if(tx<=0||ty<=0||tx>=n-1||ty>=n-1) continue;
            if(!maze[tx][ty]) continue;
            if(dis[tx][ty]<=dis[ux][uy]+1) continue;
            dis[tx][ty]=dis[ux][uy]+1;
            ee++;
            que[ee][0]=tx;
            que[ee][1]=ty;
        }
    }
} 
inline void in(bool& val){
    char in=getchar();
    while(in<=32) in=getchar();
        val=(in=='0');
} 
int main(){
    bool flag=false;
    while(~scanf("%d",&n)){
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                in(maze[i][j]);
                if(i*j&&i!=n-1&&j!=n-1){
                    s.maze[i][j]=maze[i][j];
                }
            }
        }
        if(n<=2){
            puts("");
            continue;
        }
        memset(dis,0x7f,sizeof(dis));
        for(int i=0;i<n;i++){
            if(maze[0][i]) bfs(0,i);
            if(maze[n-1][i]) bfs(n-1,i);
            if(maze[i][0]) bfs(i,0);
            if(maze[i][n-1]) bfs(i,n-1);
        } 
        deep=0;
        while(true){
            if(dfs(0,s)) break;
            deep++;
        } 
        if(flag) puts(""); flag=true;
        for(int i=0;i<deep;i++){
            if(ans[i]==0) puts("east");
            else if(ans[i]==1) puts("north");
            else if(ans[i]==2) puts("south");
            else if(ans[i]==3) puts("west");
        }
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值