📜  门| GATE-CS-2015(套装3)|第 49 题(1)

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

题目:门| GATE-CS-2015(套装3)|第 49 题

这是一道典型的图论题目,需要我们使用BFS或DFS遍历图,查找特定的门。以下是题目描述:

有一个 $m*n$ 的网格,每个格子可能是以下三种情况之一:

  1. 门,用字符 '|' 表示。

  2. 墙,用字符 '#' 表示。

  3. 空格子,用字符 '.' 表示。

从左上角的格子开始,最多可以走 $k$ 步,一步可以到达上下左右相邻的格子。请你编写一个函数 gateInGrid(K: int, grid: List[str]) -> List[List[int]],返回一个列表,其元素是一个元组 (x, y, d),表示从左上角出发,能够在走不超过 $k$ 步的情况下到达的第一扇门的坐标 $(x,y)$,以及到达该门所需的最少步数 $d$。如果从左上角无法到达任何门,则元素为 (-1,-1,-1)。

参数说明:

  • K: 最多可以走的步数,1 ≤ K ≤ 5000。
  • grid: 一个长度为 $m$ 的字符串列表,表示网格,1 ≤ m ≤ 50,1 ≤ n ≤ 50。字符串包含字符 '|','#','.',长度为 $n$。
解题思路

题目要求我们在网格中查找门,同时限制了步数,因此我们可以使用BFS或DFS遍历整个图,对于每个格子,计算它到起点的距离,在步数范围内找到最近的门即可。

以下是解题步骤:

  1. 从起点开始,使用BFS或DFS遍历整个网格,计算每个格子到起点的距离,同时记录门的位置。

  2. 遍历网格中的门,计算每个门到起点的距离,并将距离与门的位置组合成元组,添加到列表中。

  3. 对上一步得到的列表按距离进行排序,返回第一个元组,即为从左上角出发,能够在 $k$ 步内到达的最近的门。

代码实现如下:

from typing import List

def gateInGrid(K: int, grid: List[str]) -> List[List[int]]:
    
    # 遍历整个网格,计算每个格子到起点的距离
    def bfs(start: List[int], m: int, n: int, grid: List[str]) -> List[List[int]]:
        dist = [[-1] * n for _ in range(m)]
        visited = [[False] * n for _ in range(m)]
        q = [start]
        dist[start[0]][start[1]] = 0
        visited[start[0]][start[1]] = True
        while q:
            x, y = q.pop(0)
            if grid[x][y] == '|':
                continue
            for i, j in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
                nx, ny = x + i, y + j
                if 0 <= nx < m and 0 <= ny < n and not visited[nx][ny] and grid[nx][ny] != '#':
                    dist[nx][ny] = dist[x][y] + 1
                    visited[nx][ny] = True
                    q.append([nx, ny])
        return dist

    # 计算每个门到起点的距离
    def find_gates(m: int, n: int, grid: List[str], dist: List[List[int]]) -> List[List[int]]:
        gates = []
        for i in range(m):
            for j in range(n):
                if grid[i][j] == '|':
                    gates.append([i, j, dist[i][j]])
        return gates

    m, n = len(grid), len(grid[0])
    start = [0, 0]
    dist = bfs(start, m, n, grid)
    gates = find_gates(m, n, grid, dist)

    # 按距离排序,返回最近的门
    gates.sort(key=lambda x: x[2])
    for g in gates:
        if g[2] <= K:
            return [g[:2] + [g[2]]]

    return [[-1, -1, -1]]

以上代码中,我们首先在 bfs 函数中使用 BFS 遍历整个网格,计算每个格子到起点的距离;然后在 find_gates 函数中遍历网格中的门,计算每个门到起点的距离,并将距离与门的位置组合成元组,添加到列表中;最后对上一步得到的列表按距离进行排序,返回第一个元组,即为从左上角出发,能够在 $k$ 步内到达的最近的门。如果无法到达任何门,则返回 [-1, -1, -1]。

总结

本题需要我们掌握图论中 BFS 和 DFS 的基本原理,并能够熟练运用它们解决问题。在实现过程中,我们可以使用列表记录门的位置和到起点的距离,再进行排序查找,使得代码更加简洁高效。

完整代码及测试样例见下: