173 矩阵距离(多源bfs)

该博客介绍了一个求解01矩阵中多个起点到其余点的最小曼哈顿距离问题。通过将多源最短路径问题转化为单源最短路径问题,利用宽度优先搜索(BFS)算法,从所有起点开始,逐步更新并找到最短距离。代码示例展示了如何实现这一方法。
摘要由CSDN通过智能技术生成

1. 问题描述:

给定一个 N 行 M 列的 01 矩阵 A,A[i][j] 与 A[k][l] 之间的曼哈顿距离定义为:
dist(A[i][j],A[k][l])=|i−k|+|j−l|
输出一个 N 行 M 列的整数矩阵 B,其中:
B[i][j]=min1≤x≤N,1≤y≤M,A[x][y]=1dist(A[i][j],A[x][y])

输入格式

第一行两个整数 N,M。接下来一个 N 行 M 列的 01 矩阵,数字之间没有空格。

输出格式

一个 N 行 M 列的矩阵 B,相邻两个整数之间用一个空格隔开。

数据范围

1 ≤ N,M ≤ 1000

输入样例:

3 4
0001
0011
0110

输出样例:

3 2 1 0
2 1 0 0
1 0 0 1
来源:https://www.acwing.com/problem/content/description/175/

2. 思路分析:

分析题目可以知道我们需要求解多个起点到其余点的最短距离,属于多源最短路径问题,这里需要与多源多汇最短路径要区分开,多源多汇最短路求解的是任意两点之间的最短距离,而这里求解的是多个起点到其余点的最短距离,对于这种多源最短路径问题其实可以转化为单源最短路径问题,我们只需要建一个虚拟源点,从虚拟源点向所有起点连一条权重为0的边,但是在实际写代码的时候并不需要将虚拟源点建立出来,我们只需要将所有起点加入到队列中,并且将最短距离初始化为0的做法是等价的,这里与图论中求解多个起点到其余点的最短路径中的思想是类似的,都是借助于虚拟源点的思想,加入多个起点之后与之前单源bfs的步骤是一样的。

3. 代码如下:

import collections
from typing import List


class Solution:
    def bfs(self, n: int, m: int, q: collections.deque, g: List[str], dis: List[List[int]]):
        # 右左下上四个方向
        pos = [[0, 1], [0, -1], [1, 0], [-1, 0]]
        while q:
            x0, y0 = q.popleft()
            for i in range(4):
                a, b = x0 + pos[i][0], y0 + pos[i][1]
                if a < 0 or a >= n or b < 0 or b >= m: continue
                # 之前有位置到达过当前的点说明最短距离已经求解出来了直接跳过
                if dis[a][b] != -1: continue
                # 求解到达当前点的最短距离
                dis[a][b] = dis[x0][y0] + 1
                # 加入到队列中
                q.append((a, b))
        for i in range(n):
            for j in range(m):
                print(dis[i][j], end=" ")
            print()

    def process(self):
        n, m = map(int, input().split())
        g = list()
        for i in range(n):
            g.append(input())
        q = collections.deque()
        # dis可以记录最短距离并且判重
        dis = [[-1] * (m + 10) for i in range(n + 10)]
        for i in range(n):
            for j in range(m):
                # 将值为1的位置加入到队列中并且最短距离更新为0
                if g[i][j] == "1":
                    q.append((i, j))
                    dis[i][j] = 0
        self.bfs(n, m, q, g, dis)


if __name__ == '__main__':
    Solution().process()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值