[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
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:
Example 2:
Example 3:
Note:
The number of rows and columns of
Each
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]);
}
}
}
};
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
0represents uninfected cells, and
1represents
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 either
0or
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]);
}
}
}
};
相关文章推荐
- 【LeetCode】371. Sum of Two Integers 解题报告(Python)
- [leetcode] 80. Remove Duplicates from Sorted Array II 解题报告
- [LeetCode] Gray Code 解题报告
- 【LeetCode】245.Shortest Word Distance III(Medium)(加锁题)解题报告
- [Leetcode] 306. Additive Number 解题报告
- [LeetCode] Plus One 解题报告
- 【LeetCode】1.Two Sum解题报告
- Leetcode 409. Longest Palindrome 构造最长回文串 解题报告
- [leetcode] 121. Best Time to Buy and Sell Stock 解题报告
- [LeetCode] Symmetric Tree 解题报告
- [LeetCode] Rotate List 解题报告
- [LeetCode] Text Justification 解题报告
- [Leetcode] 404. Sum of Left Leaves 解题报告
- [Leetcode] 154. Find Minimum in Rotated Sorted Array II 解题报告
- [leetcode] 117. Populating Next Right Pointers in Each Node II 解题报告
- [Leetcode] 82. Remove Duplicates from Sorted List II 解题报告
- Leetcode 119. Pascal's Triangle II 杨辉三角2 解题报告
- [leetCode 解题报告]017. Letter Combinations of a Phone Number
- [leetcode] 370. Range Addition 解题报告
- LeetCode解题报告 241. Different Ways to Add Parentheses [medium]