📜  门| GATE CS Mock 2018 |设置 2 |第 60 题(1)

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

门 | GATE CS Mock 2018 | 设置 2 | 第 60 题

这道题目出自 GATE 2018 计算机科学模拟考试的第 2 阶段第 60 题,属于算法和数据结构部分的内容。

题目描述

给定一个 n 行 m 列的矩阵 matrix,其中每个元素都是 0 或 1。同时给定两个整数 x 和 y,表示矩阵中位置 (x, y) 上的元素是门。你的任务是找出最近的门到矩阵中每个位置的距离。

矩阵中的某个元素 (i, j) 到门的距离是这个元素与门之间的曼哈顿距离。与门之间的曼哈顿距离定义为这个门所在的行数与这个元素所在的行数的差的绝对值加上这个门所在的列数与这个元素所在的列数的差的绝对值。

例如,标记为门的位置是 (3, 2),矩阵的大小是 5×5,则矩阵中的每个元素到门的距离如下:

​ 2 1 0 1 2 ​ 1 0 1 2 3 ​ 0 1 2 3 4 ​ 1 2 3 4 5 ​ 2 3 4 5 6

应当注意,相同元素可以被重复多次使用,因此每个元素都需要分别计算到每个门的距离。

输入格式
  • 第一行包含两个整数 n 和 m。
  • 接下来 n 行,每行 m 个整数,表示矩阵 matrix。
  • 最后一行包含两个整数 x 和 y,表示矩阵中位置 (x, y) 上的元素是门。
输出格式

输出一个 n 行 m 列的矩阵,表示矩阵中每个位置到最近的门的距离。

输入样例
5 5
0 0 0 0 1
0 1 0 1 0
0 0 0 0 0
0 1 0 0 0
0 0 0 0 0
1 2
输出样例
3 2 1 2 0
2 1 2 1 2
3 2 3 4 3
4 1 2 3 4
5 2 3 4 5
题目分析

这道题目在图论中属于求多源最短路的问题,由于需要对矩阵中每个元素到所有门的距离进行计算,显然可以用宽度优先搜索算法(BFS)来解决。

BFS 是一种基于队列的算法,它是从给定的初始节点开始搜索,按层次逐个访问与初始节点相邻的各个节点,直到找到指定的节点或遍历所有节点。它通过一个队列来实现,具体说来,它按照某种顺序将初始节点插入到队列中,然后将与该节点相邻的所有节点也插入到队列中,标记这些节点为已访问,然后将队首的节点弹出并处理,再将与之相邻的节点插入队列尾部,以此类推。在这种方式下,搜索以广度优先的方式进行,最终到达结果。

对于矩阵中的每个门,可以使用 BFS 算法分别计算其到所有元素的距离,然后取每个元素距最近门的距离作为该元素到门的距离。

代码实现

下文代码已使用 Python3 编写,在终端下执行即可进行测试,需要注意的是,代码的实现过程并不是输出每个门到所有元素的距离,而是在 BFS 的过程中,一旦发现某个元素已被前面的门相邻时,直接用该元素到门的距离更新该元素与后面门的距离,实现原理上与前文讲解基本相同。

from collections import deque

n, m = map(int, input().split())
matrix = [list(map(int, input().split())) for _ in range(n)]
x, y = map(int, input().split())

queue = deque([(x - 1, y - 1, 0)])
visited = set([(x - 1, y - 1)])
dist = [[float('inf')] * m for _ in range(n)]
dist[x - 1][y - 1] = 0

# 分别针对每个 "1" 进行 BFS
while queue:
    i, j, d = queue.popleft()
    dist[i][j] = min(dist[i][j], d)

    if i > 0 and (i - 1, j) not in visited and matrix[i - 1][j] != 1:
        queue.append((i - 1, j, d + 1))
        visited.add((i - 1, j))
    if j > 0 and (i, j - 1) not in visited and matrix[i][j - 1] != 1:
        queue.append((i, j - 1, d + 1))
        visited.add((i, j - 1))
    if i < n - 1 and (i + 1, j) not in visited and matrix[i + 1][j] != 1:
        queue.append((i + 1, j, d + 1))
        visited.add((i + 1, j))
    if j < m - 1 and (i, j + 1) not in visited and matrix[i][j + 1] != 1:
        queue.append((i, j + 1, d + 1))
        visited.add((i, j + 1))

# 输出最终结果即可
for row in range(n):
    for col in range(m):
        print(dist[row][col], end=' ')
    print()

以下是修改后的 markdown 格式的代码片段:

```python
from collections import deque

n, m = map(int, input().split())
matrix = [list(map(int, input().split())) for _ in range(n)]
x, y = map(int, input().split())

queue = deque([(x - 1, y - 1, 0)])
visited = set([(x - 1, y - 1)])
dist = [[float('inf')] * m for _ in range(n)]
dist[x - 1][y - 1] = 0

# 分别针对每个 "1" 进行 BFS
while queue:
    i, j, d = queue.popleft()
    dist[i][j] = min(dist[i][j], d)

    if i > 0 and (i - 1, j) not in visited and matrix[i - 1][j] != 1:
        queue.append((i - 1, j, d + 1))
        visited.add((i - 1, j))
    if j > 0 and (i, j - 1) not in visited and matrix[i][j - 1] != 1:
        queue.append((i, j - 1, d + 1))
        visited.add((i, j - 1))
    if i < n - 1 and (i + 1, j) not in visited and matrix[i + 1][j] != 1:
        queue.append((i + 1, j, d + 1))
        visited.add((i + 1, j))
    if j < m - 1 and (i, j + 1) not in visited and matrix[i][j + 1] != 1:
        queue.append((i, j + 1, d + 1))
        visited.add((i, j + 1))

# 输出最终结果即可
for row in range(n):
    for col in range(m):
        print(dist[row][col], end=' ')
    print()