原文地址 zhuanlan.zhihu.com
题目描述
749. 隔离病毒 困难
病毒扩散得很快,现在你的任务是尽可能地通过安装防火墙来隔离病毒。
假设世界由 m x n
的二维矩阵 isInfected
组成, isInfected[i][j] == 0
表示该区域未感染病毒,而 isInfected[i][j] == 1
表示该区域已感染病毒。可以在任意 2 个相邻单元之间的共享边界上安装一个防火墙(并且只有一个防火墙)。
每天晚上,病毒会从被感染区域向相邻未感染区域扩散,除非被防火墙隔离。现由于资源有限,每天你只能安装一系列防火墙来隔离其中一个被病毒感染的区域(一个区域或连续的一片区域),且该感染区域对未感染区域的威胁最大且 保证唯一 。
你需要努力使得最后有部分区域不被病毒感染,如果可以成功,那么返回需要使用的防火墙个数; 如果无法实现,则返回在世界被病毒全部感染时已安装的防火墙个数。
示例 1:
1 | 输入: isInfected = [[0,1,0,0,0,0,0,1],[0,1,0,0,0,0,0,1],[0,0,0,0,0,0,0,1],[0,0,0,0,0,0,0,0]] |
示例 2:
1 | 输入: isInfected = [[1,1,1],[1,0,1],[1,1,1]] |
示例 3:
1 | 输入: isInfected = [[1,1,1,0,0,0,0,0,0],[1,0,1,0,1,1,1,1,1],[1,1,1,0,0,0,0,0,0]] |
解题思路
1 | NoYes获取当天最大的感染面积区域和所需的防火墙数目对最大感染面积区域的病毒进行阻断消杀存活的病毒进行扩散处理所需防火墙数目是否为零?输出结果 |
- 获取最大的感染面积区域和所需的防火墙数目
- 对最大感染面积区域的病毒进行阻断消杀
- 存活的病毒进行扩散处理
- 重复上述步骤,直到所需防火墙为 0 为止
如何获取最大感染面积
先遍历到病毒区域
对对每个病毒区域进行搜索
统计该区域可以感染的面积
统计该区域所需的防火墙
对当天最大病毒感染面积区域的病毒进行阻断消杀
对剩余病毒区域进行扩散处理
其中状态数s
需要特别注意,因为每一天一个位置可以有四个方向来感染,同时也可以有多个病毒区域来感染。因此要进行区分,这里就是通过状态数s
来完成的。
1 | func getMaxAreaNeedWalls() int { |
如何进行阻断消杀
- 对该病毒区域的病毒进行死亡标记
grid[x][y] = -2
- 对病毒位置进行四个方向的 DFS 搜索,同时需要做访问标记。
1 | func toDead(x, y int) { |
如何进行扩散处理
- 对当前病毒地点的四处进行 DFS 搜索。
- 如果为空,进行感染(边界条件)。
- 如果为病毒,继续搜索(状态转移)。
1 | func spread(x, y int, vis [][]int) { |
如何对病毒区域搜索
- 对当前病毒地点的四处进行 DFS 搜索。
- 如果为空,防火墙数
cur
(函数内的全局变量)自增,且未访问过的话感染面积自增(边界条件)。 - 如果为病毒,继续搜索(状态转移)。
1 | func DFS(x, y, s int, vis [][]int) int { |
AC 代码(Go 语言)
1 | // 方向数组 |