矩阵扩散 - 华为OD机试(A卷,Python题解)

华为OD机试题库《C++》限时优惠 9.9

华为OD机试题库《Python》限时优惠 9.9

华为OD机试题库《JavaScript》限时优惠 9.9

针对刷题难,效率慢,我们提供一对一算法辅导, 针对个人情况定制化的提高计划(全称1V1效率更高)。

有兴趣的同学可以扫码添加我们的VX:code5bug。

华为OD机试

题目描述

存在一个 m*n 的二维数组,其成员取值范围为0或1。其中值为1的成员具备扩散性,每经过1S,将上下左右值为0的成员同化为1,二维数组的成员初始值都为0,将第 [i, j] 和[k,l]两个位置上元素修改成1后,求矩阵的所有元素变为1需要多长时间。

输入描述

输出数据中的前2个数字表示这是一个m*n的矩阵,m和n不会超过1024大小;

中间两个数字表示一个初始扩散点位置为i,j;

最后2个数字表示另一个扩散点位置为K,l。

输出描述

输出矩阵的所有元素变为1所需要秒数。

示例1

输入:
4,4,0,0,3,3

输出:
3

说明:
输出数据中的前2个数字表示这是一个4*4的矩阵;中间两个数字表示一个初始扩散点位置为0,0;最后2个数字表示另一个扩散点位置为3,3.
给出的样例是一个很简单模型,初始点在对角线上,达到中间的位置分别为3次选代,即3秒,所以输出为3.

Python

[代码仅供学习参考并未进行大量数据测试]

from collections import deque

# 读取输入
m, n, i, j, k, l = map(int, input().split(","))

# 初始化 m*n 矩阵,全部设为 0
g = [[0] * n for _ in range(m)]

# 队列用于 BFS
q = deque()

# 两个个扩散点
q.extend([(i, j), (k, l)])
g[i][j] = g[k][l] = 1
second = 0  # 记录扩散所需秒数

# 方向数组:用于表示上下左右四个方向的偏移量
dirs = [-1, 0, 1, 0, -1]

# 执行 BFS 扩散
while q:
    size = len(q)  # 当前扩散层的大小
    for _ in range(size):
        # 处理当前层的所有节点
        curX, curY = q.popleft()

        # 遍历上下左右四个方向
        for j in range(1, 5):
            r = curX + dirs[j - 1]
            c = curY + dirs[j]

            # 判断是否越界,或者已经被扩散
            if r < 0 or c < 0 or r == m or c == n or g[r][c] == 1:
                continue

            q.append((r, c))  # 将新的扩散点加入队列
            g[r][c] = 1  # 标记当前点已扩散

    if q:
        second += 1  # 若队列仍然有元素,说明仍在扩散,时间 +1

# 输出所需时间
print(second)
题目类型

该题属于 BFS(广度优先搜索) 经典题型,类似于“多源BFS求最短路径”问题。BFS适用于求解 最短步数最少操作次数 等问题。


解题思路

  1. 构建二维矩阵

    • 读取输入,创建一个大小为 m * n 的二维数组 g,初始时所有元素均为 0,表示未被感染。
  2. 初始化BFS队列

    • 题目给出了两个初始扩散点 (i, j)(k, l),将它们入队并标记为 1(已感染),表示已经开始扩散。
  3. 执行BFS扩散

    • 采用队列进行广度优先遍历,每次从队列中取出一个点 (x, y),检查其上下左右四个方向的相邻点:

      • 若相邻点为 0(未感染),则将其加入队列,并标记为 1(已感染)。
    • 这一轮扩散完成后,时间增加 1 秒。

  4. 终止条件

  • 若所有点都被感染,则输出所需秒数。

整理题解不易, 如果有帮助到您,请给点个赞 ‍❤️‍ 和收藏 ⭐,让更多的人看到。🙏🙏🙏

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

什码情况

你的鼓励就是我最大的动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值