0
点赞
收藏
分享

微信扫一扫

牛客网搜索专题赛1007:迷宫

新鲜小饼干 2022-03-27 阅读 98

题目描述
这是一个关于二维迷宫的题目。我们要从迷宫的起点 ‘S’ 走到终点 ‘E’,每一步我们只能选择上下左右四个方向中的一个前进一格。 ‘W’ 代表墙壁,是不能进入的位置,除了墙壁以外的地方都可以走。迷宫内的 ‘D’ 代表一道上锁的门,只有在持有钥匙的时候才能进入。而 ‘K’ 则代表了钥匙,只要进入这一格,就会自动地拿到钥匙。最后 ‘.’ 则是代表空无一物的地方,欢迎自在的游荡。

本题的迷宫中,起点、终点、门跟钥匙这四个特殊物件,每一个恰好会出现一次。而且,此迷宫的四周 (最上面的一行、最下面的一行、最左边的一列以及最右边的一列) 都会是墙壁。

请问,从起点到终点,最少要走几步呢?

输入描述
输入的第一行有两个正整数H, W,分别代表迷宫的长跟宽。
接下来的H行代表迷宫,每行有一个长度恰为W的字串,此字串只包含'S', 'E', 'W', 'D ', 'K', '.'这几种字元。

输出描述
请在一行中输出一个整数代表答案,如果无法从起点走到终点,请输出-1。

输入样例
4 12
WWWWWWWWWWWW
WE.W.S…W.KW
W…D…W…W
WWWWWWWWWWWW
输出样例
20

分析:这题的难点主要是,做迷宫问题难免是需要用vis数组记录是否走过这个点,或者走完以后直接在迷宫里置这个点为不可走的状态,可是分析题意后就可以知道,我们可能会出现拿了钥匙以后还往回走的情况,比如上面的样例,从S这个地方开始左右走去,若是每个点走完都标记成再也不能走的状态,这就有可能走不到终点。但是如果不记录呢?走了还能走,这个递归或者bfs是没办法停下来的,最好的办法是:
当我们还没有拿到钥匙的时候,我们所有走过的地方都置为’D’,这是可以收到奇效的,样例里面的S从左边一直走’D’以后走不动了,就停止,但是从右边走的路线又是可以走到K的,也就是拿到钥匙以后的搜索,就成了最直接的迷宫问题了,所走到的地方都置为‘W’。

这题用dfs将会复杂很多,因为如果我们找到钥匙的路径并不是最短路径而导致多走了一些冤枉路,这是不值的,而在递归的操作中也不是很好做出一些判断剪枝。用bfs,我们根本不需要管判断是否是最短的,只要是走到终点了的,就是最短可行的路,因为这是“一群老鼠走迷宫”,不像dfs要多层递归,是“一只老鼠走迷宫”,不能实现bfs的功能。

代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,m;
char maze[505][505];
int dir[4][2]={1,0,-1,0,0,1,0,-1};
struct node{
    int x,y,flag,step;
    node(int a,int b,int c,int d){
        x=a,y=b;
        flag=c,step=d;
    }
};
int bfs(int x,int y){
    queue<node>q;
    q.push(node(x,y,0,0));
    maze[x][y]='D';
    int flag=0;
    while(!q.empty()){
        node u=q.front();
        q.pop();
        for(int i=0;i<4;++i){
            int x=u.x+dir[i][0],y=u.y+dir[i][1];
            if(x<0||x>=n||y<0||y>=m)continue;
            if(maze[x][y]=='W')continue;
            if(maze[x][y]=='E')return u.step+1;
            if(maze[x][y]=='K'){
                flag=1;
                maze[x][y]='W';
                q.push(node(x,y,flag,u.step+1));
            }
            if(maze[x][y]=='D'){
                if(u.flag)
                    q.push(node(x,y,1,u.step+1)),maze[x][y]='W';
            }
            if(maze[x][y]=='.'){
                if(u.flag)
                    q.push(node(x,y,1,u.step+1)),maze[x][y]='W';
                else
                    q.push(node(x,y,0,u.step+1)),maze[x][y]='D';
            }
        }
    }
    return -1;
}
int main(){
    cin>>n>>m;
    for(int i=0;i<n;++i)scanf("%s",maze[i]);
    for(int i=0;i<n;++i)
        for(int j=0;j<m;++j)
            if(maze[i][j]=='S')printf("%d\n",bfs(i,j));
}

举报

相关推荐

0 条评论