A virus is spreading rapidly, and your task is to quarantine the infected area by installing walls.

The world is modeled as a 2-D array of cells, where 0 represents uninfected cells, and 1 represents cells contaminated with the virus. A wall (and only one wall) can be installed between any two 4-directionally adjacent cells, on the shared boundary.

Every night, the virus spreads to all neighboring cells in all four directions unless blocked by a wall. Resources are limited. Each day, you can install walls around only one region -- the affected area (continuous block of infected cells) that threatens the most uninfected cells the following night. There will never be a tie.

Can you save the day? If so, what is the number of walls required? If not, and the world becomes fully infected, return the number of walls used.

Example 1:

Input: grid =
[[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]]
Output: 10
Explanation:
There are 2 contaminated regions.
On the first day, add 5 walls to quarantine the viral region on the left. The board after the virus spreads is: [[0,1,0,0,0,0,1,1],
[0,1,0,0,0,0,1,1],
[0,0,0,0,0,0,1,1],
[0,0,0,0,0,0,0,1]] On the second day, add 5 walls to quarantine the viral region on the right. The virus is fully contained.

Example 2:

Input: grid =
[[1,1,1],
[1,0,1],
[1,1,1]]
Output: 4
Explanation: Even though there is only one cell saved, there are 4 walls built.
Notice that walls are only built on the shared boundary of two different cells.

Example 3:

Input: grid =
[[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]]
Output: 13
Explanation: The region on the left only builds two new walls.

Note:

  1. The number of rows and columns of grid will each be in the range [1, 50].
  2. Each grid[i][j] will be either 0 or 1.
  3. Throughout the described process, there is always a contiguous viral region that will infect strictly moreuncontaminated squares in the next round.

这道题给了我们一个由0和1组成的二维数组,其中0表示健康细胞,而1表示病毒细胞,多个相邻的1组成了病毒细胞群,每天都会向周围扩散一圈,除非我们在其跟健康细胞之间建立隔离墙,这样其才会不会扩散。我们每天只能给一个病毒细胞群来建立隔离墙,其他的细胞群会进行扩散。问最终我们需要多少个隔离墙。这道题真的挺难,博主研究了好久才弄明白题目的意思。首先要明白一点,病毒细胞只会向上下左右四个方向相邻的健康细胞扩散。需要注意的一点是,需要的隔离墙的数量可能大于周围相邻的健康细胞,最明显的就是例子2中,只有一个健康细胞,但是需要四个隔离墙才能保护这个健康细胞不被感染。还有就是,我们需要隔离某个病毒细胞群的判定依据是其能感染的健康细胞的数量,而不是需要建的墙的数量或者病毒细胞的个数,这点很重要,博主之前没有注意这一点,导致fail了一个test case。所以我们要做的就是要求出每个病毒细胞群能感染的健康细胞的数量,其周围能建墙的地方,以及每个病毒细胞的位置。我们再其中选择能感染最多健康细胞的病毒细胞群进行建墙,建完墙后,我们将该群中的所有病毒细胞标记为-1,跟其他细胞区分出来。对于其他所有的病毒细胞群,将其周围能建墙的地方(即健康细胞)都标记为1,表示其现在已经被感染成了病毒细胞。然后再进行新的一轮循环检测,直到无法找出新的病毒细胞为止。

我们先找值为1的点,找到后,以其作为起点,进行BFS遍历,将和其相连的所有为1的点都找出来,在BFS遍历的过程中,如果我们检测到周围位置值为0,将其加入walls数组,表示这里可以建隔离墙,如果检测到周围位置为1,将其加入virus数组,表示这里是病毒细胞,注意起始位置也要提前加入virus数组。我们这里为了节省维度,将二维的坐标都encode成了一个int数字。BFS遍历结束后,我们根据walls数组来算出能感染的健康细胞的个数,因为我们前面提到过建隔离墙的位置可能大于健康细胞的个数,所以我们只要去除wall数组的重复项即可,利用HashSet的去重复项原理,然后将剩下的个数放入cells数组中。把cells,walls,和virus数组放入一个vector中,表示一个病毒细胞群的信息,再放入一个大数组all中,这样我们收集了所有病毒细胞群的信息后,可以根据可感染的健康细胞个数由多到少来排序,这样我们就把第一个病毒细胞群中所有virus数组的位置值变为-1,并且把可感染的健康细胞个数累加到结果res中。然后把后面所有的病毒细胞群中walls的位置值都变为1即可。当all数组为空时,跳出循环,表示没有检测到病毒细胞群或者全部都被感染了,参见代码如下:

class Solution {
public:
int containVirus(vector<vector<int>>& grid) {
int res = , m = grid.size(), n = grid[].size();
vector<vector<int>> dirs{{-,},{,},{,},{,-}};
while (true) {
unordered_set<int> visited;
vector<vector<vector<int>>> all;
for (int i = ; i < m; ++i) {
for (int j = ; j < n; ++j) {
if (grid[i][j] == && !visited.count(i * n + j)) {
queue<int> q{{i * n + j}};
vector<int> virus{i * n + j};
vector<int> walls;
visited.insert(i * n + j);
while (!q.empty()) {
auto t = q.front(); q.pop();
for (auto dir : dirs) {
int x = (t / n) + dir[], y = (t % n) + dir[];
if (x < || x >= m || y < || y >= n || visited.count(x * n + y)) continue;
if (grid[x][y] == -) continue;
else if (grid[x][y] == ) walls.push_back(x * n + y);
else if (grid[x][y] == ) {
visited.insert(x * n + y);
virus.push_back(x * n + y);
q.push(x * n + y);
}
}
}
unordered_set<int> s(walls.begin(), walls.end());
vector<int> cells{(int)s.size()};
all.push_back({cells ,walls, virus});
}
}
}
if (all.empty()) break;
sort(all.begin(), all.end(), [](vector<vector<int>> &a, vector<vector<int>> &b) {return a[][] > b[][];});
for (int i = ; i < all.size(); ++i) {
if (i == ) {
vector<int> virus = all[][];
for (int idx : virus) grid[idx / n][idx % n] = -;
res += all[][].size();
} else {
vector<int> wall = all[i][];
for (int idx : wall) grid[idx / n][idx % n] = ;
}
}
}
return res;
}
};

参考资料:

https://discuss.leetcode.com/topic/114208/c-dfs-12ms

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Contain Virus 包含病毒的更多相关文章

  1. [LeetCode] 749. Contain Virus 包含病毒

    A virus is spreading rapidly, and your task is to quarantine the infected area by installing walls. ...

  2. [LeetCode] Contains Duplicate 包含重复值

    Given an array of integers, find if the array contains any duplicates. Your function should return t ...

  3. Virus:病毒查杀

    简介 小伙伴们,大家好,今天分享一次Linux系统杀毒的经历,还有个人的一些总结,希望对大家有用. 这次遇到的是一个挖矿的病毒,在挖一种叫门罗币(XMR)的数字货币,行情走势请看 https://ww ...

  4. Leetcode 600.不包含连续1的非负整数

    不包含连续1的非负整数 给定一个正整数 n,找出小于或等于 n 的非负整数中,其二进制表示不包含 连续的1 的个数. 示例 1: 输入: 5 输出: 5 解释: 下面是带有相应二进制表示的非负整数&l ...

  5. hdu 2896 病毒侵袭 AC自动机(查找包含哪些子串)

    病毒侵袭 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  6. 【HDU2896】病毒侵袭 AC自动机

    [HDU2896]病毒侵袭 Problem Description 当太阳的光辉逐渐被月亮遮蔽,世界失去了光明,大地迎来最黑暗的时刻....在这样的时刻,人们却异常兴奋--我们能在有生之年看到500年 ...

  7. HDU2896 病毒侵袭 —— AC自动机

    题目链接:https://vjudge.net/problem/HDU-2896 病毒侵袭 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit ...

  8. HDU2896 病毒侵袭

    题目大意:给出若干病毒的特征码,不超过500个.每个病毒的特征码长度在20~200之间.现在有若干网站的源代码,要检测网站的源代码中是否包含病毒.网站的个数不超过1000个,每个网站的源代码长度在70 ...

  9. hdu2896 病毒侵袭 ac自动机

    地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=2896 题目: 病毒侵袭 Time Limit: 2000/1000 MS (Java/Othe ...

随机推荐

  1. canvas填充样式

    填充样式主要针对fillStyle.fillStyle除了可以赋值为color,还可以赋值渐变色,包括线性渐变色和径向渐变色,还是和css3里的内容类似. 一.线性渐变 1.设置线性渐变的填充样式 设 ...

  2. 光环国际联合阿里云推出“AI智客计划”

    2018阿里巴巴云栖大会深圳峰会3月28日.29日在大中华喜来登酒店举行,阿里云全面展示智能城市.智能汽车.智能生活.智能制造等产业创新. 3月28日下午,以"深化产教融合,科技赋能育人才& ...

  3. RESTFul API设计指南及使用说明

    RESTFul API设计指南及使用说明 一. 协议 API与用户的通信协议,使用HTTP协议. 二. 域名 应尽量将API部署在专用域名之下(http://api.example.com) 也可以将 ...

  4. 走进webpack(3)-- 小结

    写这一系列的文章,本意是想要梳理一下自己凌乱的webpack知识,只是使用过vue-cli,修改过其中的一部分代码,但是对于一个简单项目从0开始搭建webpack的流程和其中的依赖并不是十分清楚.所以 ...

  5. JavaScript(第三十二天)【Ajax】

    2005年Jesse James Garrett发表了一篇文章,标题为:"Ajax:A new Approach to Web Applications".他在这篇文章里介绍了一种 ...

  6. beta冲刺3-咸鱼

    一,昨天的问题: 页面整理还没做 我的社团这边的后台数据库未完成,前端代码修改未完成. 二,今天已完成 页面整理基本完成,把登陆独立出来了,然后基本处理掉了多余页面(反正也没几个--) 我的社团这边试 ...

  7. 第一次作业:扑通扑通 我的IT

    让我掉下眼泪的不止昨夜的酒,还有这满屏的代码. 第一部分:结缘计算机 你为什么选择计算机专业?你认为你的条件如何?和这些博主比呢? 在炎炎的夏日,伴随这高三的结束,我也面临大学专业的选择,我看着书里密 ...

  8. 2017-2018-1 Java演绎法 第三周 作业

    团队任务:团队展示与选题 团队展示 队员学号及姓名 学号 姓名 主要负责工作 20162315 马军 日常统计,项目部分代码 20162316 刘诚昊 项目部分代码,代码质量测试 20162317 袁 ...

  9. 项目Alpha冲刺Day8

    一.会议照片 二.项目进展 1.今日安排 前端界面框架基本完成,剩下侧边栏与权限相关部分未完成.前端路由异常拦截完成.项目结构与开发流程规定完成.后台开发规定小变更. 2.问题困难 组件的拆分与否和组 ...

  10. 201621123062《java程序设计》第五周作业总结

    1. 本周学习总结 1.1 写出你认为本周学习中比较重要的知识点关键词 关键词:interface.Comparable.comparator 1.2 尝试使用思维导图将这些关键词组织起来.注:思维导 ...