[LeetCode] Contain Virus 包含病毒
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:
- The number of rows and columns of
gridwill each be in the range[1, 50]. - Each
grid[i][j]will be either0or1. - 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 包含病毒的更多相关文章
- [LeetCode] 749. Contain Virus 包含病毒
A virus is spreading rapidly, and your task is to quarantine the infected area by installing walls. ...
- [LeetCode] Contains Duplicate 包含重复值
Given an array of integers, find if the array contains any duplicates. Your function should return t ...
- Virus:病毒查杀
简介 小伙伴们,大家好,今天分享一次Linux系统杀毒的经历,还有个人的一些总结,希望对大家有用. 这次遇到的是一个挖矿的病毒,在挖一种叫门罗币(XMR)的数字货币,行情走势请看 https://ww ...
- Leetcode 600.不包含连续1的非负整数
不包含连续1的非负整数 给定一个正整数 n,找出小于或等于 n 的非负整数中,其二进制表示不包含 连续的1 的个数. 示例 1: 输入: 5 输出: 5 解释: 下面是带有相应二进制表示的非负整数&l ...
- hdu 2896 病毒侵袭 AC自动机(查找包含哪些子串)
病毒侵袭 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- 【HDU2896】病毒侵袭 AC自动机
[HDU2896]病毒侵袭 Problem Description 当太阳的光辉逐渐被月亮遮蔽,世界失去了光明,大地迎来最黑暗的时刻....在这样的时刻,人们却异常兴奋--我们能在有生之年看到500年 ...
- HDU2896 病毒侵袭 —— AC自动机
题目链接:https://vjudge.net/problem/HDU-2896 病毒侵袭 Time Limit: 2000/1000 MS (Java/Others) Memory Limit ...
- HDU2896 病毒侵袭
题目大意:给出若干病毒的特征码,不超过500个.每个病毒的特征码长度在20~200之间.现在有若干网站的源代码,要检测网站的源代码中是否包含病毒.网站的个数不超过1000个,每个网站的源代码长度在70 ...
- hdu2896 病毒侵袭 ac自动机
地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=2896 题目: 病毒侵袭 Time Limit: 2000/1000 MS (Java/Othe ...
随机推荐
- windows上SSH服务连接远程主机失败
putty连接出现错误提示"Network error:connection refused",xshell连接出现错误提示"connection failed:(por ...
- kvm之十二:虚拟机迁移
虚拟机迁移该方式要确保虚拟机是关机状态.virsh shutdown snalevirsh dumpxml snale > /etc/libvirt/qemu/snale_qy.xml // ...
- 跟着大神学zookeeper分布式锁实现-----来自Ruthless
前几天分享了@Ruthless大神的Redis锁,发现和大家都学习了很多东西.因为分布式锁里面,最好的实现是zookeeper的分布式锁.所以在这里把实现方式和大家分享一下. zookeeper分布式 ...
- [LTR] 信息检索评价指标(RP/MAP/DCG/NDCG/RR/ERR)
一.RP R(recall)表示召回率.查全率,指查询返回结果中相关文档占所有相关文档的比例:P(precision)表示准确率.精度,指查询返回结果中相关文档占所有查询结果文档的比例: 则 PR 曲 ...
- Entity Framework——并发策略
使用EF框架遇到并发时,一般采取乐观并发控制. 1支持并发检验 为支持并发检验,需要对实体进行额外的设置.默认情况下是不支持并发检验的.有以下两种方式: 方式名称 说明 时间戳注解/行版本 使用Tim ...
- 2018上C语言程序设计(高级)作业- 第2次作业
作业要求一 提交截图: 6-7: 6-8: 6-9: 7-1: 作业要求二 题目6-7删除字符中数字字符 1.设计思路: (1)第一步:本题要求是删除字符中的数字字符,我的主要思路是通过数组遍历若遇到 ...
- 【转载】NetFPGA-1G-CML从零开始环境配置
##环境 深度Linux ###环境配置 ```bash sudo apt-get install libsigc++ sudo apt-get install qgit sudo apt-get i ...
- Struts2之Struts2的下载与安装
Struts2的下载 登陆struts的官网 下载Full Distribution这个选项的struts2的包. 这是Struts2的完整版,里面包括Struts2的实例应用,空实例应用,核心库,源 ...
- day-7 一个简单的决策树归纳算法(ID3)python编程实现
本文介绍如何利用决策树/判定树(decision tree)中决策树归纳算法(ID3)解决机器学习中的回归问题.文中介绍基于有监督的学习方式,如何利用年龄.收入.身份.收入.信用等级等特征值来判定用户 ...
- Spring Cache扩展:注解失效时间+主动刷新缓存(二)
*:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...