解法:可以发现,子岛屿会被父岛屿包围起来,导致子岛屿是不能借助海水延伸到边界的。
而父岛屿,是能借助海水或者本身就在边界处了。
那么只需要用bfs 每找出一块岛屿,就判断一下这块岛屿能不能通过海水延伸到边界以外,如果可以,此时答案+1。 为了方便处理,我们可以在外围加上一圈海水。
这里要注意两个点,通过海水延伸是可以8个方向的,也是一个踩坑点。
然后,每次判断一个岛屿能不能跑到边界,需要初始化标记数组,避免和之前的岛屿判断产生冲突。
// 只有 不是子岛屿的 岛屿 才能跑到边界
#include<iostream>
#include<cstring>
#include<queue>
#define x first
#define y second
using namespace std;
const int N=60;
char g[N][N];
bool st[N][N];
bool st2[N][N];
int n,m;
typedef pair<int,int>PII;
int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
int bdx[8]={0,1,0,-1,1,1,-1,-1},bdy[8]={1,0,-1,0,1,-1,1,-1};
void init()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
}
void bfs(int x,int y)
{
queue<PII>q;
q.push({x,y});
st[x][y]=true;
while(q.size())
{
PII p = q.front();
q.pop();
for(int i=0;i<4;i++)
{
int a = p.x + dx[i];
int b = p.y + dy[i];
if(a<=0||a>n||b<=0||b>m||st[a][b]||g[a][b]=='0')continue;
st[a][b]=true;
q.push({a,b});
}
}
}
bool bbfs(int x,int y)
{
queue<PII>q;
q.push({x,y});
memset(st2,false,sizeof st2);
st2[x][y]=true;
while(q.size())
{
PII p = q.front();
q.pop();
for(int i=0;i<8;i++)
{
int a = p.x + bdx[i];
int b = p.y + bdy[i];
if(st2[a][b]||g[a][b]=='1')continue;
if(a==0||a==n||b==0||b==m)return true;
st2[a][b]=true;
q.push({a,b});
}
}
return false;
}
int main()
{
init();
int t;
cin>>t;
while(t--)
{
int res=0;
memset(g,'0',sizeof g);
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
cin>>g[i][j];
}
memset(st,false, sizeof st);
//如果是岛屿,就把他能延申到的点都标记, 再判断这个岛屿能不能跑到边界
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(!st[i][j]&&g[i][j]=='1')
{
bfs(i,j);
//不是子岛屿
// cout<<i<<" "<<j<<endl;
if(bbfs(i,j))
{
res++;
}
}
}
}
cout<<res<<endl;
}
}