问题描述:
解题思路:
首先,我们需要注意,当一个岛屿被淹没分成两个甚至更多岛屿的情况,这种情况下被淹没的岛屿本质上只是淹没一个。因此我们不能直接用原来的岛屿数减淹没后的小岛个数。
所以我们需要给原本的岛屿做上颜色标记,则淹没后剩余的颜色总数就是被淹的小岛数。再用原来的岛屿数减剩余的颜色总数就是答案
具体步骤:1.染色(dfs)2.计算颜色数 3.ans
题解:
#include<bits/stdc++.h>
using namespace std;
const int N = 1005;
char mp[N][N]; // 选择字符类型数组
int n, scc, col[N][N]; // scc:颜色 col[][]:颜色数组,内部放位置的颜色
// 四个方向
int dy[] = {0, 0, 1, -1};
int dx[] = {1, -1, 0, 0};
bool vis[N * N]; // 颜色标记数组
// 染色dfs
void dfs(int x, int y){
col[x][y] = scc;
for(int i = 0; i < 4; i++){ // 四个方向染色
int nx = x + dx[i], ny = y + dy[i];
if(mp[nx][ny] == '.' || col[nx][ny])continue; // 因为边界就是海说以不需要具体的边界限
制。当该点是海或是有颜色就下一步
dfs(nx, ny);
}
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++)cin >> mp[i][j];
}
// 染色:当该点是空白岛屿时对该点做dfs以染色整个岛
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
if(mp[i][j] == '.' || col[i][j])continue;
scc++;
dfs(i, j);
}
}
// 计算淹没后剩余颜色:不用做淹没后图,直接在每个四个方向都是岛的点计算颜色数(因为他们肯定不会被淹没)。当找到一个没被标记的颜色就标记他
int ans = 0;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
if(mp[i][j] == '.')continue;
bool tag = true;
for(int k = 0; k < 4; k++){
int x = i + dx[k], y = j + dy[k];
if(mp[x][y] == '.')tag = false;// 判断上下左右是不是岛,是就返回ture
}
if(tag){ // 上下左右是岛的情况下再判断有没有被标记
if(!vis[col[i][j]])ans++;
vis[col[i][j]] = true;
}
}
}
cout << scc - ans << '\n'; // 颜色总数(总岛屿数) - 剩余岛屿数 = 淹没数
return 0;
}
知识点:dfs