本博客含有一道题目: 病毒在封闭空间中的传播时间
病毒在封闭空间中的传播时间
问题描述
在一个封闭的房间中,排列着 n 行 m 列的座位,每个座位间距为 1 米。房间中每个座位上都坐着一人,部分人戴了口罩,部分人未戴口罩。已知房间中有一位已经感染病毒的人,病毒可以每秒向相邻座位传播 1 米。对于戴口罩的人,病毒需要两秒才能成功感染,或者需要在一秒内从两个相邻的感染者处同时被感染。设计一个算法,计算病毒感染房间内所有人所需的最短时间。
问题理解
-
你需要在一个
n x m的座位矩阵中,计算病毒从初始感染者传播到所有人的最短时间。 -
每个座位上的人可能戴口罩(
seats[i][j] == 1)或未戴口罩(seats[i][j] == 0)。 -
病毒传播规则:
- 未戴口罩的人(
seats[i][j] == 0):病毒可以在1秒内传播到该座位。 - 戴口罩的人(
seats[i][j] == 1):病毒需要2秒才能传播到该座位,或者需要在一秒内从两个相邻的感染者处同时被感染。
- 未戴口罩的人(
我的思路
-
利用BFS进行遍历
-
如果没有戴口罩,则病毒传播时间为当前时间加一。
- 如果该位置未被感染,则更新该位置感染时间
- 如果该位置被感染,则让当前病毒传播时间与之前的感染时间进行对比,将较小值进行更新。
-
如果戴口罩,则病毒传播时间为当前时间加二。
- 如果该位置未被感染,则更新该位置感染时间
- 如果该位置被感染,则让当前病毒传播时间与之前的感染时间进行对比,将较小值进行更新。
- 同时需要检查该位置是否同时被两个感染源感染,如果是的话,将更新值与当前时间加一进行比较,并用较小值进行更新。
-
遍历完成之后,找到最大值并进行输出。
豆包思路
-
初始化:将初始感染者的位置和时间(0秒)加入队列,并将其感染时间设置为0。
-
BFS遍历:从队列中取出当前感染者的位置和时间,遍历其四个相邻的座位。
- 对于每个相邻座位,计算新的感染时间。
- 如果相邻座位上的人戴口罩,检查是否有两个相邻的感染者,如果有,则可以在1秒内感染。
- 如果新的感染时间比当前记录的感染时间短,更新感染时间并将其加入队列。
-
终止条件:当队列为空时,BFS结束。
-
返回结果:找到
infected_time矩阵中的最大值,即为病毒感染所有人的最短时间。
融合思路编程
from collections import deque
def solution(row_n, column_m, seats, patient):
directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
queue = deque([(patient[0], patient[1], 0)]) # (行, 列, 时间)
infected_time = [[float('inf')] * column_m for _ in range(row_n)]
infected_time[patient[0]][patient[1]] = 0
while queue:
r, c, time = queue.popleft()
for dr, dc in directions:
nr, nc = r + dr, c + dc
if 0 <= nr < row_n and 0 <= nc < column_m:
new_time = time + 1 if seats[nr][nc] == 0 else time + 2
if seats[nr][nc] == 1: # 戴口罩
adjacent_infected = sum(1 for dr2, dc2 in directions
if 0 <= nr + dr2 < row_n and 0 <= nc + dc2 < column_m
and infected_time[nr + dr2][nc + dc2] == time)
if adjacent_infected >= 2:
new_time = min(new_time, time + 1)
if new_time < infected_time[nr][nc]:
infected_time[nr][nc] = new_time
queue.append((nr, nc, new_time))
max_time = max(max(row) for row in infected_time)
return max_time if max_time != float('inf') else -1
总结
通过使用BFS算法,你可以有效地计算病毒从初始感染者传播到所有人的最短时间。关键在于正确处理戴口罩的人的感染逻辑,并确保在每一步中更新感染时间。