📌  相关文章
📜  门| Sudo GATE 2020 Mock III(2019 年 1 月 24 日)|第 57 题(1)

📅  最后修改于: 2023-12-03 15:42:20.068000             🧑  作者: Mango

题目描述

给定一个n x m的矩阵表示一个迷宫。1表示门,0表示墙壁。你被困在墙壁中,需要找到门的位置并通过它逃脱。假设迷宫的所有边框均为墙壁。你只能上下左右移动,并且每次移动只能走一个单位。你不能穿过墙壁,也不能走到矩阵外部。

实现函数int escape(int maze,int n, int m);输入参数解释:

maze是整数类型的二维数组,其中1表示门,0表示墙壁,n和m分别表示迷宫的行列数。

输出:一个整数数组,包含两个元素,第一个元素表示你从始点到出口的最短路径长度,第二个元素表示你的最短路径能够穿过的门的数量(不包括第0个始点门)。

##算法

这道题可以使用广度优先算法来解决。该算法使用队列进行实现,从始点出发,依次遍历与该点相连的其他节点。当找到终点时,我们就可以停止算法。在此基础上,我们可以统计到终点的最短路径长度以及路径中经过的门的数量。

##算法流程

  1. 创建一个队列,然后把始点放入队列中,并把该点的距离和穿越的门数设为0.

  2. 从该队列中弹出一个节点,然后遍历若干连通节点。

  3. 如果该节点没有被遍历过,则把该节点放入队列中,并更新该节点到始点的距离和穿越门的数量。

  4. 重复步骤2-3,直到找到终点。

  5. 返回距离和穿越门的数量.

##代码实现

from queue import Queue

def escape(maze, n, m):
    #创建队列,把起点坐标和经过门的数量入队列
    q = Queue()
    q.put((0,0,0))
    #用于记录该节点是否已经遍历过
    visited = [[False] * m for _ in range(n)]
    #设置到(0,0)的最短距离和穿越的门的数量为0
    dist = [[0] * m for _ in range(n)]
    #开始遍历队列中的节点
    while not q.empty():
        x,y,doors = q.get()
        #如果找到终点,直接返回
        if maze[x][y] == 1:
            return [dist[x][y],doors]
        #遍历当前节点的上下左右节点
        for dx,dy in [(0,1),(0,-1),(1,0),(-1,0)]:
            nx,ny = x+dx,y+dy
            #如果节点越界或者是墙,直接忽略
            if 0<=nx<n and 0<=ny<m and maze[nx][ny] != -1:
                #如果该节点没有遍历过
                if not visited[nx][ny]:
                    visited[nx][ny] = True
                    dist[nx][ny] = dist[x][y]+1
                    #如果该节点是门
                    if maze[nx][ny] == 1:
                        q.put((nx,ny,doors+1))
                    else:
                        q.put((nx,ny,doors))
    return [-1,-1]

##复杂度分析

时间复杂度:

该算法中,每个节点最多只被遍历一次。故时间复杂度为O(n*m)。其中n和m分别为迷宫的行列数。

空间复杂度:

我们需要使用O(n*m)的空间来存储dist和visited数组.和一个标准队列的额外空间。故空间复杂度为O(n * m)。