在做完这道题时,我看了一下别人的题解,觉得不是很好理解,就分享一下我的吧,这题可以先标记未在环内的海洋和环的边缘的陆地,接着将未被标记的元素全部置为1(因为可以把子岛屿看成大岛屿(环)的组成部分),这样就可以求只需要剩下的岛屿1的个数就可以了,值得一提的是,判断一个环需要从8个方向判断。
#include <bits/stdc++.h>
using namespace std;
const int N = 52;
int a[N][N], ans = 0;
int dx[5] = { -1,1,0,0 };
int dy[5] = { 0,0,-1,1 };
int dx1[8] = { -1,-1,0,1,1,1,0,-1 };
int dy1[8] = { 0,1,1,1,0,-1,-1,-1 };
int m, n;
bool b[N][N], vis[N][N];
void dfs(int x, int y)
{
b[x][y] = 1;
for (int i = 0; i < 8; i++)
{
int nx = x + dx1[i], ny = y + dy1[i];
if (nx >= 0 && ny >= 0 && nx <= m + 1 && ny <= n + 1 && b[nx][ny] == 0 && a[nx][ny] != 1)
{
dfs(nx, ny);
}
}
}
void dfs2(int x, int y)
{
vis[x][y] = 1;
for (int i = 0; i < 4; i++)
{
int nx = x + dx[i], ny = y + dy[i];
if (nx >= 1 && ny >= 1 && nx <= m && ny <= n && vis[nx][ny] == 0 && a[nx][ny] == 1)
{
dfs2(nx, ny);
}
}
}
int main()
{
int t;
cin >> t;
while (t--)
{
cin >> m >> n;
memset(b, 0, sizeof(b));
memset(vis, 0, sizeof(vis));
memset(a, 0, sizeof(a));
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++)
scanf("%1d", &a[i][j]);
ans = 0;
dfs(0, 0);
for (int i = 1; i <= m; i++)
{
for (int j = 1; j <= n; j++)
{
if (!b[i][j])
a[i][j] = 1;
}
}
for (int i = 1; i <= m; i++)
{
for (int j = 1; j <= n; j++)
{
if (!vis[i][j] && a[i][j] == 1)
{
ans++;
dfs2(i,j);
}
}
}
cout << ans << endl;
}
return 0;
}