计算疫情扩散时间

题目描述

在一个地图中, 地图由n*n个区域组成, 有部分区域被感染病菌. 感染区域每天都会把周围 (上下左右) 的4个区域感染.

请根据给定的地图计算, 多少天以后, 全部区域都会被感染. 如果初始地图上所有区域全部都被感染, 或者没有被感染区域, 返回-1.

输入描述

一行N*N个数字, 只包含0,1, 不会有其他数字, 表示一个地图, 数字间用,分割, 0表示未感染区域, 1表示已经感染区域.

每N个数字表示地图中一行, 输入数据共表示N行N列的区域地图.

例如输入 1,0,1,0,0,0,1,0,1, 表示地图:

1,0,1
0,0,0
1,0,1

输出描述

一个整数, 表示经过多少天以后, 全部区域都被感染 1<=N<200.

示例1

输入:

1,0,1,0,0,0,1,0,1

输出:

2

说明: 1天以后, 地图中仅剩余中心点未被感染; 2天以后全部被感染.

示例2

输入:

1,1,1,1,1,1,1,1,1

输出:

-1

说明: 全部都感染.

题解

Python

import math

def main():
    # 先读取输入
    # 得到一个 N*N 的二维数组
    array = list(map(int, input().split(",")))

    AFFECTED = 1
    UNAFFECTED = 0

    # 然后检查感染区域, 如果全是0或者全是1, 就返回-1
    # 否则就模拟每天的感染情况
    all_affected = all(x == AFFECTED for x in array)
    all_unaffected= all(x == UNAFFECTED for x in array)
    if all_affected or all_unaffected:
        print(-1)
        return

    # 计算二维数组的边界
    rows = int(math.sqrt(len(array)))
    columns = rows
    assert rows * rows == len(array)
    assert 1 <= rows < 200

    # 将一维数组转换成二维数组, 方便进行定位
    matrix = [array[row * columns: (row + 1) * columns] for row in range(rows)]

    # 可能的感染方向
    directions = ((1, 0), (-1, 0), (0, 1), (0, -1))

    # 创建新一天的感染快照, 注意这里使用深拷贝, 解除两个数组间的关联
    snapshot = matrix[:]
    # 持续感染的天数
    days = 0
    # 计算还未被感染的区域数量
    unaffected_remains = len(array) - len(list(x for x in array if x == UNAFFECTED))

    # 持续感染, 直到扩散到所有区域
    while unaffected_remains > 0:
        for row in range(rows):
            for col in range(columns):
                if matrix[row][col] == UNAFFECTED:
                    # 当前区域尚未被感染, 等待被感染
                    pass
                else:
                    # 去感染相邻四周
                    for dx, dy in directions:
                        row2 = row + dx
                        col2 = col + dy
                        # 检查新区域的有效性, 它是否已被感染
                        if 0 <= row2 < rows and 0 <= col2 < columns and snapshot[row2][col2] == UNAFFECTED:
                            snapshot[row2][col2] = AFFECTED
                            unaffected_remains -= 1
        # 更新当天的感染情况
        days += 1
        # 注意这里是深拷贝
        matrix = snapshot[:]

    print(days)

if __name__ == "__main__":
    main()