📅  最后修改于: 2023-12-03 15:28:44.456000             🧑  作者: Mango
这是一道典型的图论题目,需要我们使用BFS或DFS遍历图,查找特定的门。以下是题目描述:
有一个 $m*n$ 的网格,每个格子可能是以下三种情况之一:
门,用字符 '|' 表示。
墙,用字符 '#' 表示。
空格子,用字符 '.' 表示。
从左上角的格子开始,最多可以走 $k$ 步,一步可以到达上下左右相邻的格子。请你编写一个函数 gateInGrid(K: int, grid: List[str]) -> List[List[int]],返回一个列表,其元素是一个元组 (x, y, d),表示从左上角出发,能够在走不超过 $k$ 步的情况下到达的第一扇门的坐标 $(x,y)$,以及到达该门所需的最少步数 $d$。如果从左上角无法到达任何门,则元素为 (-1,-1,-1)。
参数说明:
题目要求我们在网格中查找门,同时限制了步数,因此我们可以使用BFS或DFS遍历整个图,对于每个格子,计算它到起点的距离,在步数范围内找到最近的门即可。
以下是解题步骤:
从起点开始,使用BFS或DFS遍历整个网格,计算每个格子到起点的距离,同时记录门的位置。
遍历网格中的门,计算每个门到起点的距离,并将距离与门的位置组合成元组,添加到列表中。
对上一步得到的列表按距离进行排序,返回第一个元组,即为从左上角出发,能够在 $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 的基本原理,并能够熟练运用它们解决问题。在实现过程中,我们可以使用列表记录门的位置和到起点的距离,再进行排序查找,使得代码更加简洁高效。
完整代码及测试样例见下: