蓝桥杯 岛屿个数 刷题笔记

1.岛屿个数 - 蓝桥云课

一道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;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值