[Algo] 洪水填充
1. 被围绕的区域
// 1. 被围绕的区域
// https://leetcode.cn/problems/surrounded-regions/description/
void dfs1(vector<vector<char>>& board, int i, int j)
{
int n = board.size();
int m = board[0].size();
if (i < 0 || j < 0 || i >= n || j >= m || board[i][j] != 'O') return;
board[i][j] = 'F';
dfs1(board, i - 1, j);
dfs1(board, i + 1, j);
dfs1(board, i, j - 1);
dfs1(board, i, j + 1);
}
void solve(vector<vector<char>>& board) {
int n = board.size();
int m = board[0].size();
for (int j = 0; j < m; j++) dfs1(board, 0, j);
for (int j = 0; j < m; j++) dfs1(board, n - 1, j);
for (int i = 1; i < n - 1; i++) dfs1(board, i, 0);
for (int i = 1; i < n - 1; i++) dfs1(board, i, m - 1);
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
{
if (board[i][j] == 'F') board[i][j] = 'O';
else if (board[i][j] == 'O') board[i][j] = 'X';
}
}
2. 最大人工岛
// 2. 最大人工岛
// https://leetcode.cn/problems/making-a-large-island/
void dfs2(vector<vector<int>>& grid, int i, int j, int cnt)
{
int n = grid.size();
int m = grid[0].size();
if (i < 0 || j < 0 || i >= n || j >= m || grid[i][j] != 1) return;
grid[i][j] = cnt;
dfs2(grid, i - 1, j, cnt);
dfs2(grid, i + 1, j, cnt);
dfs2(grid, i, j - 1, cnt);
dfs2(grid, i, j + 1, cnt);
}
int largestIsland(vector<vector<int>>& grid) {
int n = grid.size();
int m = grid[0].size();
int cnt = 1;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
{
if (grid[i][j] == 1) dfs2(grid, i, j, ++cnt);
}
unordered_map<int, int> island;
bool all_one = true;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
{
if (grid[i][j] != 0) island[grid[i][j]]++;
else all_one = false;
}
if (all_one) return n * m;
int ans = 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
if (grid[i][j] == 0)
{
set<int> s;
int cur = 1;
if (i != 0 && grid[i - 1][j] != 0) s.insert(grid[i - 1][j]);
if (j != 0 && grid[i][j - 1] != 0) s.insert(grid[i][j - 1]);
if (i != n - 1 && grid[i + 1][j] != 0) s.insert(grid[i + 1][j]);
if (j != m - 1 && grid[i][j + 1] != 0) s.insert(grid[i][j + 1]);
for (auto index : s) cur += island[index];
ans = max(ans, cur);
}
return ans;
}
3. 打砖块
// 3. 打砖块
// https://leetcode.cn/problems/bricks-falling-when-hit/
int cnt = 0;
int get(vector<vector<int>>& grid, int i, int j)
{
int n = grid.size();
int m = grid[0].size();
if (i < 0 || j < 0 || i >= n || j >= m) return -1;
return grid[i][j];
}
void dfs3(vector<vector<int>>& grid, int i, int j)
{
int n = grid.size();
int m = grid[0].size();
if (i < 0 || j < 0 || i >= n || j >= m || grid[i][j] != 1) return;
grid[i][j] = 2;
cnt++;
dfs3(grid, i - 1, j);
dfs3(grid, i + 1, j);
dfs3(grid, i, j - 1);
dfs3(grid, i, j + 1);
}
vector<int> hitBricks(vector<vector<int>>& grid, vector<vector<int>>& hits) {
vector<int> ans;
for (int i = 0; i < hits.size(); i++) grid[hits[i][0]][hits[i][1]]--;
for (int j = 0; j < grid[0].size(); j++) dfs3(grid, 0, j);
for (int i = hits.size() - 1; i >= 0; i--)
if (++grid[hits[i][0]][hits[i][1]] == 1)
{
// 两种情况需要进行洪水填充: 1. 与顶部相连 2. 与其他已经填充的砖块相连
if (hits[i][0] == 0 || get(grid, hits[i][0] - 1, hits[i][1]) == 2
|| get(grid, hits[i][0] + 1, hits[i][1]) == 2
|| get(grid, hits[i][0], hits[i][1] + 1) == 2
|| get(grid, hits[i][0], hits[i][1] - 1) == 2)
{
cnt = 0;
dfs3(grid, hits[i][0], hits[i][1]);
ans.push_back(cnt - 1);
}
else ans.push_back(0);
}
else ans.push_back(0);
reverse(ans.begin(), ans.end());
return ans;
}