P8662 题解
一道深度优先搜索题。
搜索每个岛屿在淹没后的情况,判断连通块,注意一块岛屿淹没后有可能变成两块,不要直接判断连通块。
算法流程:
- 找到一个陆地。
- 广搜遍历连通块。
- 修改岛屿。
- 再次广搜判断是否增加或减少。
如下:
.........
.##...##.
.#######.
.##...##.
.........
代码:
#include <bits/stdc++.h>
using namespace std;
int n, a[1007][1007], b[1007][1007], ca = 0, cnta = 0, ans = 0, via[1007][1007], v[100007];
char ch;
int dx[] = {0, 1, -1, 0, 0};
int dy[] = {0, 0, 0, 1, -1};
inline void dfsa(int x, int y) {
if (via[x][y] == 0)
ca++, via[x][y] = ++cnta;
fr(4) {
int tx = x + dx[i], ty = y + dy[i];
if (a[tx][ty] == 1 && 1 < tx && tx < n && 1 < ty && ty < n && !via[tx][ty]) {
via[tx][ty] = via[x][y];
dfsa(tx, ty);
}
}
}
int main() {
ios::sync_with_stdio(false);
cin >> n;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) {
cin >> ch;
if (ch == '#')
a[i][j] = 1;
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (a[i][j] && via[i][j] == 0)
dfsa(i, j);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (a[i][j] == 1)
if (a[i - 1][j] == 1 && a[i + 1][j] == 1 && a[i][j - 1] == 1 && a[i][j + 1] == 1)
b[i][j] = 1;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (b[i][j] == 1 && via[i][j])
v[via[i][j]] = 1;
for (int i = 1; i <= cnta; i++) {
ans += (v[i] == 1);
}
cout << ca - ans << endl;
return 0;
}