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. 使用Listview控件显示数据

    1.图像列表控件 ImageList是含有图像对象的集合,可以通过索引或关键字引用该集合中的每个对象. ImageList空间的属性 属性 说明 Images 存储在图像列表中的所有图像 ImageS ...

  2. JavaOOP-继承

    继承 1.继承的概念 继承是类与类之间的关系,是一个很简单很直观的概念,与现实世界中的继承(例如儿子继承父亲财产)类似. 继承可以理解为一个类从另一个类获取方法和属性的过程.如果类B继承于类A,那么B ...

  3. Suricata 之IPS模式

    IPS 1.Suricata 本身是不具有拦截功能的,想要让它拦截包需要配合 iptables 使用. 首先要确定安装的suricata是否支持IPS模式,如果在安装编译的时候没有启用IPS模式,NF ...

  4. Item 15: 只要有可能,就使用constexpr

    本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 如果说C++11中有什么新东西能拿"最佳困惑奖" ...

  5. 关于hbase中的hbase-site.xml 配置详解

    该文档是用Hbase默认配置文件生成的,文件源是 hbase-default.xml hbase.rootdir 这个目录是region server的共享目录,用来持久化HBase.URL需要是'完 ...

  6. 听翁恺老师mooc笔记(9)--枚举

    枚举类型的定义 用符号而不是具体的数字来表示程序中的数字,这么表示的好处是可读性,当别人看你的程序,看到的是单词,很容易理解这些数字背后的含义,那么用什么符号来表示名字哪?需要const int常量的 ...

  7. alpha-咸鱼冲刺day1

    一,合照 emmmmm.自然是没有的. 二,项目燃尽图 三,项目进展 登陆界面随意写了一下.(明天用来做测试的) 把学姐给我的模板改成了自家的个人主页界面,侧边栏啥的都弄出来了(快撒花花!) 四,问题 ...

  8. 冲刺NO.5

    Alpha冲刺第五天 站立式会议 项目进展 今日项目完成内容主要包括了JS的学习,事务管理员模块与学生模块的完善与补充,并且开始编写信用信息管理模块和奖惩事务管理模块. 问题困难 前端部分的技术掌握的 ...

  9. XCode Build Settings中几种Search Paths

    Header search path:去查找头文件的路径,同在在你需要使用第三方库的时候,在这里设置你的头文件路径目录,如图 <code><span class="str& ...

  10. 织梦dedecms默认网站地图sitemap.html优化

    网站地图对于网站优化很重要,搜索引擎就是靠网站地图去收录网站页面,本文主要讲解优化织梦自带的网站地图功能.     织梦自带的网站地图使用方法:织梦后台--生成--HTML更新--更新网站地图,可以在 ...