📜  门| Sudo GATE 2021 测验 |第 46 题(1)

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

Sudo GATE 2021 测验 |第 46 题

题目描述

本题给定一个由 '0''1' 组成的矩阵,其中 '0' 表示一个门,'1' 表示墙壁。你的任务是求解从矩阵任意一扇门出发到达其他任意一扇门所需的最小步数。

函数说明
def minimum_step_to_reach_the_other_door(n: int, m: int, arr: List[List[str]]) -> int:
    pass
参数说明
  • n:表示矩阵的行数,约束范围为 $1 \leq n \leq 1000$。
  • m:表示矩阵的列数,约束范围为 $1 \leq m \leq 1000$。
  • arr:表示矩阵,一个由类型为 List 且长度为 mList 组成的 List,其中每个子 List 等长,且其元素为 '0''1'
返回值说明
  • 返回一个整数,表示从矩阵任意一扇门出发到达其他任意一扇门所需的最小步数。
  • 若不存在一条能够从矩阵任意一扇门出发到达其他任意一扇门的路径,则返回 -1
示例

输入:

n = 5
m = 5
arr = [['0', '1', '1', '0', '0'],
       ['0', '0', '0', '1', '0'],
       ['1', '1', '0', '0', '1'],
       ['1', '1', '1', '1', '0'],
       ['1', '0', '0', '1', '0']]

输出:

9
实现思路

从所有的门出发,通过广搜算法找到所有门之间的最短路径,最后取最小值即可。

完整代码
from typing import List, Tuple, Dict, Any, Union


def minimum_step_to_reach_the_other_door(n: int, m: int, arr: List[List[str]]) -> int:
    queue = []
    visited = {}
    ans = float('inf')
    for i in range(n):
        for j in range(m):
            if arr[i][j] == '0':
                queue.append((i, j, 0))
                visited[(i, j)] = True
    if len(queue) == 1:
        return 0
    dx = [0, 0, 1, -1]
    dy = [1, -1, 0, 0]
    while len(queue) != 0:
        x, y, steps = queue.pop(0)
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            if 0 <= nx < n and 0 <= ny < m and (nx, ny) not in visited and arr[nx][ny] == '0':
                queue.append((nx, ny, steps+1))
                visited[(nx, ny)] = True
                if len(visited) == len(queue)+1:
                    ans = min(ans, steps+1)
    return ans if ans != float('inf') else -1
时间复杂度

广搜算法的平均时间复杂度为 $O(V+E)$ ,其中 $V$ 为节点数(门的个数), $E$ 为边数(相邻门之间的距离总和),在本题中即为所有门之间的距离总和。

在最坏情况下,所有格子都是门,假设门数量为 $k$,则 $V=k$,$E=\frac{k(k-1)}{2}$,则广搜的时间复杂度为 $O(k^2)$。特别地,当 $k=1$ 时(即只有一扇门),其时间复杂度为 $O(1)$。

因此,本题的时间复杂度为 $O(k^2)$,其中 $k \leq nm$。

空间复杂度

空间复杂度为 $O(k)$,其中 $k$ 为门的数量。