📌  相关文章
📜  门| Sudo GATE 2020 Mock I(2019 年 12 月 27 日)|问题 37(1)

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

问题描述

对于一个表示由若干道门所连接的两个房间的迷宫,我们可以使用二维数组 maze 表示,其中 maze[i][j] 为 0 表示该位置可以到达,maze[i][j] 为 1 表示该位置不可到达。请你计算从起点 start 到终点 destination 最少需要几步。

如果无法到达终点,请返回 -1。

注意:

  • 仅能在maze[i][j]为0的位置上走。
  • 寻找起点和终点的时候,只会存在一个起点和一个终点。
例子
输入:
maze = [[0, 0, 1, 0, 0],
        [0, 0, 0, 0, 0],
        [0, 0, 0, 1, 0],
        [1, 1, 0, 1, 1],
        [0, 0, 0, 0, 0]],
start = [0, 4], destination = [4, 4]
输出: 12
解释: 我们可以寻找以下路径来到达终点:
左 -> 下 -> 下 -> 左 -> 左 -> 下 -> 下 -> 右 -> 右 -> 下 -> 下 -> 右。
总步数为 12。
解题思路

由于需要求从一个点到另一个点的最短路径,自然想到使用 BFS 算法。

我们从起点开始,并将其加入到队列中。然后在每一步中,我们取队列首部的节点,并考虑一下所有可以到达的相邻节点。若该相邻节点在迷宫中没有被访问过(也就是没有走过),我们对该节点进行标记并将其加入队列中,并且记录一下步数。若在某一时刻,我们找到了终点,那么我们就可以直接返回或者在 BFS 过程中使用一些剪枝技巧来加速搜索。最后,若我们到达了队列为空,那么就说明从起点无法到达终点。

代码实现

以下是 Python 3 语言的解题代码实现:

class Solution:
    def shortestDistance(self, maze: List[List[int]], start: List[int], destination: List[int]) -> int:
        ROW, COL = len(maze), len(maze[0])
        visited = set()
        queue = collections.deque([(start[0], start[1], 0)])
        directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]

        while queue:
            x, y, steps = queue.popleft()

            if [x, y] == destination:
                return steps

            if (x, y) in visited:
                continue

            visited.add((x, y))

            for dx, dy in directions:
                nx, ny = x, y

                # 向一个方向走到尽头
                while 0 <= nx + dx < ROW and 0 <= ny + dy < COL and maze[nx + dx][ny + dy] == 0:
                    nx += dx
                    ny += dy

                if (nx, ny) not in visited:
                    queue.append((nx, ny, steps + abs(nx - x) + abs(ny - y)))

        return -1

其中,我们使用了集合 visited 存储走过的位置,使用队列 queue 来进行 BFS,并使用 directions 列出可能的方向(向上走、向下走、向左走、向右走)。最后,也就是找到终点 destination,我们返回最短距离 steps。