lanqiao OJ 3513 岛屿个数(2023省赛)

简介: lanqiao OJ 3513 岛屿个数(2023省赛)

原题链接:3.岛屿个数 - 蓝桥云课 (lanqiao.cn)

感觉这个题出的真的特别好,考察了对bfs的使用,包括连通性的一系列判断,如果对bfs掌握的不熟练真的很难想出如何下手来做这道题。

这里我们需要用海水来进行bfs,海水可以渗透,也就是说可以走8个方向,因为我们要从任意一个边界点出发,所以我们需要把图扩展一下,变成n+2,m+2的图,我们把第0行第0列,和n+1行,n+1列变成0,也就是海水,这样的话我们从0,0开始遍历,就可以从每一个边界点进入判断,当然,我们的越界条件也要变成 n+2 , 和 m+2(这里真的很重要www , 博主刚开始做这道题,因为没有判别好边界问题导致直接全wa,要是这是在考场上这样,不得直接寄了,本来就不会几道),然后当我们第一次搜到一个岛屿的时候,他的初始状态是1,也就是说我们还没有搜索到过这个岛屿,这样的话我们就把最终答案 ans ++ ,然后对这个岛屿进行染色,染色当然很简单,就是一个判定连通性的问题,把这个1联通的所有1都变成2 ,这样就表示我们已经搜过这个岛屿了,如果这个岛屿内部也有岛屿,而且外面这个岛屿是封闭的我们的外界海水就渗透不进去,那我们就不会搜索到子岛屿,子岛屿也就不会参与计数;

#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
 
using namespace std ;
const int N = 100 ;
int d1[4][2] = {{0,1},{0,-1},{1,0},{-1,0}} ;
int d2[8][2] = {{0,1},{0,-1},{1,0},{-1,0},{1,1},{-1,1},{1,-1},{-1,-1}} ;
struct node{//这是我们记录搜索到的点的坐标
  int x , y;
  node(int xx ,int yy){
    x = xx , y = yy ;
  }
  bool operator < (const node & o) const {
    if(x == o.x) return y < o.y ;
    else return x < o.x ;
  }
};
queue<node> q ;//用于bfs
char mp[N][N] ;//存图
int n , m ;
int ans ;//返回值
void dfs(int x, int y){//染色,判断岛屿的上下左右四个方向,如果有陆地的话,索命他们是联通的,就对他们进行染色
  mp[x][y] = '2' ;
  for(int i = 0 ; i < 4 ; i ++){
    int tx = x + d1[i][0] , ty = y + d1[i][1] ;
    if(mp[tx][ty] == '1'){
      dfs(tx,ty) ;
    }
    
  }
}
 
void bfs1(){
  q.push(node(0,0)) ;
  while(!q.empty()){
    node now = q.front() ;
    q.pop() ;
    int x = now.x , y = now.y ;
    for(int i = 0 ; i < 8 ; i ++){
      int tx = x + d2[i][0] , ty = y + d2[i][1] ;
      if(tx<0||tx>n+1||ty<0||ty>m+1||mp[tx][ty] == '2') continue ;//越界或者已经搜索过了
      if(mp[tx][ty] == '1'){
        ans ++ ; dfs(tx,ty) ;//如果碰到新的陆地就进行染色
      }
      if(mp[tx][ty] == '0'){//如果是海水,就进入队列让下一个海水继续渗透
        mp[tx][ty] = '2' ; 
        q.push(node(tx,ty)) ;
      }
    }
  } 
}
 
int main(){
  int t ; cin >> t ;
  while(t --){
    ans = 0 ;
    memset(mp,'0',sizeof(mp));
    cin >> n >> m ;
    for(int i = 0 ; i <= n ; i++) mp[i][0] = '0' ;//对边界进行初始化,保证从所有边界点的海水进行渗透
    for(int j = 0 ; j <= m ; j++) mp[0][j] = '0' ;
    for(int i = 1 ; i <= n ; i ++){
      for(int j = 1 ; j <= m ; j ++){
        cin >> mp[i][j] ;
      }
    }
    bfs1() ;
    cout << ans << endl ;
  }
  
}
目录
相关文章
|
3天前
lanqiao OJ 1447 砝码称重
lanqiao OJ 1447 砝码称重
12 1
|
3天前
lanqiao OJ 689 四阶幻方
lanqiao OJ 689 四阶幻方
10 0
|
3天前
lanqiao OJ 1505 剪邮票
lanqiao OJ 1505 剪邮票
10 0
|
3天前
lanqiao OJ 364 跳石头
lanqiao OJ 364 跳石头
18 6
|
3天前
lanqiao OJ 664 方格填数
lanqiao OJ 664 方格填数
6 1
|
3天前
lanqiao OJ 99 分巧克力
lanqiao OJ 99 分巧克力
8 1
|
3天前
lanqiao OJ 108 发现环
lanqiao OJ 108 发现环
8 1
|
1天前
lanqiao oj 186 糖果(状态压缩dp)
lanqiao oj 186 糖果(状态压缩dp)
5 0
|
2天前
lanqiao OJ 2097 青蛙过河
lanqiao OJ 2097 青蛙过河
6 0
|
1天前
lanqiao OJ 207 大臣的旅费(两次dfs)
lanqiao OJ 207 大臣的旅费(两次dfs)
6 0