一道BFS题 关键在于 联通块的判断 和 子岛的判定
1. 关于连通块
遍历每一个点
对于一个点 x,y 如果是陆地 放进去BFS并将该点连接的陆地设置成 已被遍历
同时将 x,y存入数组 ans用于一会的子岛检查
由于每个点都会搜索自己连接的陆地 所以再次被放入BFS的一定是一个新岛
2. 关于子岛的判断
我们把图从1,1 开始存到 N,m 最外面一圈都是 0 作为边界的海
如果是一个岛在往周围搜索的过程中没有被环包住 那么该岛是可以搜到边界的外海的
对于3 不是子岛 我们发现 3 可以在搜到2 的上面时 斜着钻出去 这样就可以搜到边界了
也就是没有被包围不判断为子岛
所以我们在判断连通块时 搜四个方向
检查能否搜到外海时搜八个方向
注意点 :
1.每次读入新的数据 要把所有数组 和 计数器重置一下
2.队列要在函数里面开 不然可能在进行下一次搜索时 取到上次遗留的数据
3,bfs函数的i 只开到了四 检查四个方法 check函数i开到了8 检查八个方向
#include<bits/stdc++.h>
#include<iostream>
#include<queue>
using namespace std;
int n,m;
#define Check(x,y)(x >= 1 && x <= n && y >= 1 && y <= m)
#define Checks(x,y)(x >= 0 && x <= n+1 && y >= 0 && y <= m+1)
int dx[8] = { -1,0,1,0,-1,-1,1,1 };//前四个为上下左右 判断连通块 后四个为斜方向
int dy [8]= { 0,1,0,-1,-1,1,-1,1};
const int N = 55 ;
int a[N][N];
bool st[N][N];
int ans[2500][2] ;
struct node{
int x;
int y;
};
void bfs(int x,int y)
{
queue <node> q;
queue <node> p;
node start ,next;
start.x = x;
start.y = y;
q.push(start);
while(!q.empty()){
start = q.front();
q.pop();
for(int i = 0;i < 4;i++){
next.x = start.x +dx[i];
next.y = start.y +dy[i];
if(a[next.x][next.y] == 1
&& Check(next.x,next.y) //连通块判断 是1 且没有越界 且 没有被搜过
&& st[next.x][next.y] == false )
{
st[next.x][next.y] = true;
q.push(next);
}
}
}
}
int t,res;
bool checks(int x,int y){
queue <node> q;
queue <node> p;
memset(st,0,sizeof st);
node start ,next;
start.x = x;
start.y = y;
q.push(start);
while(!q.empty()){
start = q.front();
q.pop();
for(int i = 0;i < 8;i++){
next.x = start.x +dx[i];
next.y = start.y +dy[i];
//从周围的海进入 沿着海搜
if(a[next.x][next.y] == 0 &&
// 如果搜到的是海
Checks(next.x,next.y)&&
st[next.x][next.y] == false )
{
//如果 搜到了四边的任意一个海返回true
if(next.x == 0||next.y==0){
return true;
}
st[next.x][next.y] = true;
q.push(next);
}
}
}
return false;//如果搜完了都没搜到 返回false
}
int main(){
cin>>t;
while(t>0){
int x,y;
cin>>x>>y;
n = x ,m = y;
int k;
memset(a,0,sizeof a);
for(int i = 1 ;i <= n ;i++){
for(int j = 1 ; j <= m;j++){
char c;
cin >> c;
a[i][j] = c - '0';
}
}
int anss = 0;
memset(ans,0,sizeof ans);
memset(st,0,sizeof st);
for(int i = 1 ;i <= n ;i++){
for(int j = 1 ;j <= m ;j++){
if(st[i][j] == false && a[i][j] == 1){
bfs(i,j);
//存入 岛屿数组
ans[anss][0] =i;
ans[anss][1] =j;
anss++;
}
}
}
res = 0 ;
for(int i = 0; i < anss;i++){
if(checks(ans[i][0],ans[i][1])){
//检查能否搜到外海
res++;
}
}
cout<<res<<endl;
t--;
}
return 0;
}