📌  相关文章
📜  僵尸通过仅向上、向左、向下和向右感染来感染所有人类所需的最少时间(1)

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

僵尸感染问题

问题描述

有一群人类和一些僵尸,僵尸可以通过感染人类而变成僵尸。假设人类和僵尸分别用数字 0 和 1 表示,那么在一个矩阵里,1 表示僵尸,0 表示人类。僵尸每秒钟可以将上下左右四个方向上与之相邻的人类感染成僵尸,问至少需要多少时间才能将所有人类变成僵尸。

解法

这是一个经典的图论问题,可以用广度优先搜索 (BFS) 来解决。思路是将矩阵中的每个僵尸看做图中的节点,将每个节点的四个邻居看做节点之间的连边,然后从所有的僵尸开始做 BFS,找到离每个人类最近的僵尸,并更新其感染时间。最后所有人类的最小感染时间即为答案。

代码实现
from queue import Queue

def min_infection_time(grid):
    # 定义方向向量
    directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]

    # 初始化 BFS 队列和尺寸
    q = Queue()
    m, n = len(grid), len(grid[0])

    # 记录访问状态和最短感染时间
    visited = [[False] * n for _ in range(m)]
    time = [[0] * n for _ in range(m)]

    # 将所有僵尸加入队列并标记为已访问
    for i in range(m):
        for j in range(n):
            if grid[i][j] == 1:
                q.put((i, j))
                visited[i][j] = True

    # BFS 遍历
    while not q.empty():
        x, y = q.get()
        for dx, dy in directions:
            nx, ny = x + dx, y + dy
            if 0 <= nx < m and 0 <= ny < n and not visited[nx][ny]:
                visited[nx][ny] = True
                time[nx][ny] = time[x][y] + 1
                q.put((nx, ny))

    # 找到所有人类中的最小感染时间
    ans = max(max(row) for row in time)
    if ans == 0:  # 如果本来就没有人类,返回 0
        return 0
    else:
        return ans

# 测试示例
grid = [[0, 1, 1, 0, 1],
        [0, 1, 0, 1, 0],
        [0, 0, 0, 0, 1],
        [0, 1, 0, 0, 0]]
print(min_infection_time(grid))  # 输出 2
性能分析

上述算法的时间复杂度为 $O(mn)$,其中 $m$ 和 $n$ 分别为矩阵的行数和列数,因为我们需要访问每个节点。空间复杂度也为 $O(mn)$,因为我们需要记录每个节点的访问状态和最短感染时间。因此,该算法是可行的,可以通过本题的所有测试用例。