您的位置:首页 > 大数据 > 人工智能

[Leetcode] 749. Contain Virus 解题报告

2018-03-14 11:09 411 查看
题目

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 
grid
 will each be in the range 
[1,
50]
.
Each 
grid[i][j]
 will be either 
0
 or 
1
.
Throughout the described process, there is always a contiguous viral region that will infect strictly more uncontaminated squares in the next round.
思路

这是一道比较繁琐的DFS题目,我们将题目的求解分为如下几个步骤:1)遍历各个细菌群,找出下一步受感染最多的一个细菌群;2)将这个群里的细菌用墙隔离起来(实现中就是将cells的值置为-1);3)模拟其余细菌群的扩展过程,修改cells的值。重复上面3个步骤,直到找不出需要进一步隔离的细菌群即可。

代码

class Solution {
public:
int containVirus(vector<vector<int>>& grid) {
int total_walls = 0;
while (true) { // if still some virus are infecting
int walls = process(grid);
if (walls == 0) {
break;
}
total_walls += walls;
}
return total_walls;
}
private:
int process(vector<vector<int>> &grid) {
int row_num = grid.size(), col_num = grid[0].size();
int max_area = 0, max_walls = 0, color = -1, row = -1, col = -1;
// using different color to indicate being affected by different virus
vector<vector<int>> visited(row_num, vector<int>(col_num, 0));
for (int r = 0; r < row_num; ++r) {
for (int c = 0; c < col_num; ++c) {
if (grid[r][c] == 1 && visited[r][c] == 0) {
int walls = 0;
int area = dfs(grid, visited, r, c, color, walls);
if (area > max_area) {
max_area = area;
row = r, col = c;
max_walls = walls;
}
--color;
}
}
}
// set this virus region inactive
buildWall(grid, row, col);
// propagate other virus by 1 step
visited = vector<vector<int>>(row_num, vector<int>(col_num, 0));
for (int r = 0; r < row_num; ++r) {
for (int c = 0; c < col_num; ++c) {
if (grid[r][c] == 1 && visited[r][c] == 0) {
spread(grid, visited, r, c);
}
}
}
return max_walls;
}
int dfs(vector<vector<int>>& grid, vector<vector<int>>& visited,
int row, int col, int color, int& walls) {
int row_num = grid.size(), col_num = grid[0].size(), area = 0;
if (row < 0 || row >= row_num || col < 0 || col >= col_num) {
return 0;
}
if (grid[row][col] == 0) {
++walls;
if (visited[row][col] == color) {
return 0;
}
visited[row][col] = color;
return 1;
}
// grid[row][col] could be -1, inactive virus
if (visited[row][col] == 1 || grid[row][col] != 1) {
return 0;
}
visited[row][col] = 1;
vector<vector<int>> dir = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
for (int i = 0; i < 4; ++i) {
area += dfs(grid, visited, row + dir[i][0], col + dir[i][1], color, walls);
}
return area;
}
void buildWall(vector<vector<int>>& grid, int row, int col) {
int row_num = grid.size(), col_num = grid[0].size();
if (row < 0 || row >= row_num || col < 0 || col >= col_num || grid[row][col] != 1) {
return;
}
grid[row][col] = -1; //set inactive
vector<vector<int>> dir = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
for (int i = 0; i < 4; ++i) {
buildWall(grid, row + dir[i][0], col + dir[i][1]);
}
}
void spread(vector<vector<int>>& grid, vector<vector<int>>& visited, int row, int col) {
int row_num = grid.size(), col_num = grid[0].size();
if (row < 0 || row >= row_num || col < 0 || col >= col_num || visited[row][col] == 1) {
return;
}
if (grid[row][col] == 0) {
grid[row][col] = 1;
visited[row][col] = 1;
}
else if (grid[row][col] == 1) {
visited[row][col] = 1;
vector<vector<int>> dir = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
for (int i = 0; i < 4; ++i) {
spread(grid, visited, row + dir[i][0], col + dir[i][1]);
}
}
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: