【限时免费】20天拿下华为OD笔试之【BFS】2023Q1A-计算网络信号【闭着眼睛学数理化】全网注释最详细分类最全的华为OD真题题解

【BFS】2023Q1A-计算网络信号

题目描述与示例

网络信号经过传递会逐层衰减,且遇到阻隔物无法直接穿透,在此情况下需要计算某个位置的网络信号值。注意:网络信号可以绕过阻隔物

  • array[m][n] 的二维数组代表网格地图,
  • array[i][j] = 0 代表 ij 列是空旷位置;
  • array[i][j] = x ( x 为正整数)代表 ij 列是信号源,信号强度是 x;
  • array[i][j] = -1 代表 ij 列是阻隔物.
  • 信号源只有 1 个,阻隔物可能有 0 个或
  • 网络信号衰减是上下左右相邻的网格衰减 1
  • 现要求输出对应位置的网络信号值。

输入

输入为三行:

第一行为 mn,代表输入是一个 m × n的数组。

第二行是一串 m × n 个用空格分隔的整数。每连续 n 个数代表一行,再往后 n 个代表下一行,以此类推。 对应的值代表对应的网格是空矿位置,还是信号源,还是阻隔物。

第三行是 ij,代表需要计算 array[i][j] 的网络信号值。注意:此处ij均从 0 开始,即第一行 i0

例如

6 5
0 0 0 -1 0 0 0 0 0 0 0 0 -1 4 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0
1 4

代表如下地图

【限时免费】20天拿下华为OD笔试之【BFS】2023Q1A-计算网络信号【闭着眼睛学数理化】全网注释最详细分类最全的华为OD真题题解_第1张图片

需要输出第 1 行第 4 列的网络信号值,如下图,值为 2

【限时免费】20天拿下华为OD笔试之【BFS】2023Q1A-计算网络信号【闭着眼睛学数理化】全网注释最详细分类最全的华为OD真题题解_第2张图片

输出

输出对应位置的网络信号值,如果网络信号未覆盖到,也输出 0。

一个网格如果可以途径不同的传播衰减路径传达,取较大的值作为其信号值。

示例一

输入

6 5
0 0 0 -1 0 0 0 0 0 0 0 0 -1 4 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0
1 4

输出

2

示例二

输入

6 5
0 0 0 -1 0 0 0 0 0 0 0 0 -1 4 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0
2 1

输出

0

说明

输出-1。右下角的区域,被周边三个死亡区挡住,无法实现改造。

备注

  1. m不一定等于nm < 100n < 100 ,网络信号小于 1000
  2. 信号源只有 1 个,阻隔物可能有 0 个或多个。
  3. 输入的 mn与第二行的数组是合法的,无需处理数量对不上的异常情况。
  4. 要求输出信号值的位置,不会是阻隔物。

解题思路

注意,本题和LC994. 腐烂的橘子几乎完全一致,属于计算BFS层数的问题,而且只有一个信号源,所以使用常规的单源BFS方法即可完成。

要注意以下几点:

  • 输入的数据是一个长度为m*n的一维数组,需要转换成我们常用的grid二维矩阵。
  • 本题可以直接在grid上进行元素修改,最终输出要求的点(target_x, target_y)的强度值grid[target_x][target_y]即可。
  • 由于直接对grid进行修改,如果某个点的强度已经从0修改为其他值,说明已经进入过,故无需重复使用checkList进行检查。
  • 搜索层数可以从信号源的强度intensity不断-1来判断,无需从level = 0开始递增。

代码

# 题目:2023Q1A-计算网络信号
# 分值:200
# 作者:许老师-闭着眼睛学数理化
# 算法:多源BFS
# 代码看不懂的地方,请直接在群上提问

from collections import deque

# 搜索的四个方向
D = [(0,1), (1,0), (-1,0), (0,-1)]

m, n = map(int, input().split())
lst = list(map(int, input().split()))
target_x, target_y = map(int, input().split())

# 需要把lst转化为常用的grid二维数组
grid = list()
for i in range(0, m*n, n):
    # lst中的每n个元素作为一行,存入grid中
    grid.append(lst[i:i+n])

q = deque()

# 双重循环遍历grid,寻找信号源
for i in range(m):
    for j in range(n):
        # 0表示空地,-1表示阻碍,故grid[i][j]大于0时,点(i,j)是信号源
        if grid[i][j] > 0:
            # 将信号源存入队列q中,作为BFS的起始位置
            q.append((i, j))
            # 获得信号源的强度intensity
            intensity = grid[i][j]
            # 由于有且只有一个信号源,所以找到信号源后直接退出循环
            break

# 注意,本题可以直接在grid数组上进行修改,故无需设置checkList检查数组
# 另外,搜索层数可以根据intensity递减
while len(q) > 0:
    # 本次搜索,强度-1
    intensity -= 1
    # 如果强度降为0,无需进行搜索,直接退出循环
    if intensity == 0:
        break

    # 获得当前队列长度,为本层BFS需要出队的节点数
    qSize = len(q)
    for _ in range(qSize):
        # 弹出当前队头元素点(x, y)
        x, y = q.popleft()
        # 遍历点(x, y)的近邻点
        for dx, dy in D:
            nx, ny = x+dx, y+dy
            # (nx, ny)需要满足:
            # 1. 不越界
            # 2. 在grid中为0
            if (0 <= nx < m and 0 <= ny < n and grid[nx][ny] == 0):
                # 直接将grid[nx][ny]修改为强度intensity
                # 这一步替代了checkList
                grid[nx][ny] = intensity
                # 并且将点(nx, ny)加入队列中继续进行搜索
                q.append((nx, ny))


# 最后输出grid中点(target_x, target_y)的值即可
print(grid[target_x][target_y])

时空复杂度

时间复杂度:O(MN)。需要遍历整个grid二维数组。

空间复杂度:O(1)。无需checkList,不考虑grid二维数组所占空间,仅需若干常数变量。

华为OD算法/大厂面试高频题算法练习冲刺训练

  • 华为OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务100+同学成功上岸!

  • 课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化

  • 每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!

  • 60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁

  • 可上全网独家的欧弟OJ系统练习华子OD、大厂真题

  • 可查看链接 OD算法冲刺训练课程表 & OD真题汇总(持续更新)

  • 绿色聊天软件戳 od1336了解更多

你可能感兴趣的:(华为OD真题,#,BFS,华为od,宽度优先,算法)