当前位置: 首页 > news >正文

蓝桥杯真题 3513.岛屿个数

  原题地址:1.岛屿个数 - 蓝桥云课

问题描述

小蓝得到了一副大小为 M×NM×N 的格子地图,可以将其视作一个只包含字符 '0'(代表海水)和 '1'(代表陆地)的二维数组,地图之外可以视作全部是海水,每个岛屿由在上/下/左/右四个方向上相邻的 '1' 相连接而形成。

在岛屿 AA 所占据的格子中,如果可以从中选出 kk 个不同的格子,使得他们的坐标能够组成一个这样的排列:(x0,y0),(x1,y1),…,(xk−1,yk−1)(x0​,y0​),(x1​,y1​),…,(xk−1​,yk−1​),其中 (xi+1modk,yi+1modk)(xi+1modk​,yi+1modk​) 是由 (xi,yi)(xi​,yi​) 通过上/下/左/右移动一次得来的 (0≤i≤k−1)(0≤i≤k−1),此时这 kk 个格子就构成了一个“环”。如果另一个岛屿 BB 所占据的格子全部位于这个“环”内部,此时我们将岛屿 BB 视作是岛屿 AA 的子岛屿。若 BB 是 AA 的子岛屿,CC 又是 BB 的子岛屿,那 CC 也是 AA 的子岛屿。

请问这个地图上共有多少个岛屿?在进行统计时不需要统计子岛屿的数目。

输入格式

第一行一个整数 TT,表示有 TT 组测试数据。

接下来输入 TT 组数据。对于每组数据,第一行包含两个用空格分隔的整数 MM、NN 表示地图大小;接下来输入 MM 行,每行包含 NN 个字符,字符只可能是 '0' 或 '1'。

输出格式

对于每组数据,输出一行,包含一个整数表示答案。

样例输入

2
5 5
01111
11001
10101
10001
11111
5 6
111111
100001
010101
100001
111111

样例输出

1
3

        这个题同时用了dfs和bfs,首先先用bfs将将所有不同的岛屿进行染色操作,用于区分各个岛屿。其次每一次将一个岛屿染色后都要紧接着从该岛屿的首格出发向周围的八个方向,进行dfs深度搜索 。如果某一条路线上碰到了别的岛屿就结束当前的递归,如果出现了某一条路径可以抵达grid的边界,那么就证明该岛屿并没有被其他岛屿;因为如果该岛屿被其他岛屿包围,当dfs遍历到其他岛屿时就会结束递归,就不可能到达grid的边界。

具体代码如下:

#include <iostream>
#include <vector>
#include <cstring>
#define PII pair<char,char>
using namespace std;

int row,col;
int cnt = 0;
int dic[4][2] = {{-1,0},{0,1},{1,0},{0,-1}};
int dict[8][2] = {{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};
char grid[55][55];
bool visited[55][55];
PII q[2550];//模拟队列
void bfs(int x,int y){
    int front = 0,rear = 0;//队头和队尾
    q[rear++] = {x,y};
    grid[x][y] = '1' + cnt;//染色操作
    while (front < rear){
        PII t = q[front++];//取出队头坐标
        for (int i = 0;i < 4;++i){//将队头坐标的四个方向的合法坐标依次入队
            int xx = t.first + dic[i][0];
            int yy = t.second + dic[i][1];
            if (xx >= 0 && xx < row && yy >= 0 && yy < col)
            {
                if (grid[xx][yy] == '1')
                {
                    grid[xx][yy] = '1' + cnt;
                    q[rear++] = {xx,yy};
                }
            }
        }
    }
}
bool dfs(int x,int y){
    //当在某一个方向可以到达边界时,就证明该岛屿并没有被其他岛屿所包围
    if (x == 0 || x == row - 1 || y == 0 || y == col - 1)
        return true;
    visited[x][y] = true;

    for (int i = 0;i < 8;++i){
        int xx = x + dict[i][0];
        int yy = y + dict[i][1];
        //'1' + cnt为当前岛屿所染的色
        if (!visited[xx][yy] && (grid[xx][yy] == '0' || grid[xx][yy] == '1' + cnt))
        {
            //当前位置是海,或者没有到其他岛屿的范围就继续搜索
            if (dfs(xx,yy))
                return true;
        }
    }
    return false;
}
int main()
{
    int t;
    cin>>t;
    for (int i = 0;i < t;++i){
        int res = 0;
        cin>>row>>col;
        for (int j = 0;j < row;++j){
            cin>>grid[j];
        }
        cnt = 1;//从第一个岛屿开始,将第一个岛屿染色为cnt + 1
        for (int j = 0;j < row;++j){
            for (int k = 0;k < col;++k){
                if (grid[j][k] == '1')
                {
                    //进行染色操作
                    bfs(j,k);
                    //初始化visited数组
                    memset(visited,0,sizeof(visited));
                    if (dfs(j,k))//从点(j,k)开始向八个方向进行寻找,看是否能到达边界,是的话就证明该岛屿并没有被某个岛屿完全包围
                        res++;
                    cnt++;
                }
            }
        }
        cout<<res<<endl;
    }
    return 0;
}

相关文章:

  • doris:时区管理
  • 学习笔记:黑马程序员JavaWeb开发教程(2025.3.22)
  • 鱼书--学习2
  • Python入门基础
  • 【数据分享】2000—2024年我国省市县三级逐年归一化植被指数(NDVI)数据(年平均值/Shp/Excel格式)
  • MySQL数据库精研之旅第二期:库操作的深度探索
  • 计算机基础:编码04,认识反码和补码
  • 深度学习3-pytorch学习
  • python学习笔记--实现简单的爬虫(二)
  • AutoImageProcessor代码分析
  • Python设计模式 - 适配器模式
  • 二十四、实战开发 uni-app x 项目(仿京东)- 前后端实现登录注册
  • 在线生成自定义二维码
  • 失物招领|校园失物招领系统|基于Springboot的校园失物招领系统设计与实现(源码+数据库+文档)
  • 【 <二> 丹方改良:Spring 时代的 JavaWeb】之 Spring Boot 中的异常处理:全局异常与自定义异常
  • 【自学笔记】Linux基础知识点总览-持续更新
  • 利用Dify编制用户问题意图识别和规范化回复
  • C#单例模式
  • 常考计算机操作系统面试习题(二)(中)
  • Windows——电脑无法正常上网的一种解决办法
  • 美国多地爆发集会抗议特朗普政府多项政策
  • 停电催生商机,中国品牌 “照亮” 西班牙
  • 证监会:坚决拥护党中央对王建军进行纪律审查和监察调查决定
  • 马上评|科学谋划“十五五”,坚定不移办好自己的事
  • 秦洪看盘|资金切换主线,重构市场风格
  • 4月人民币对美元即期汇率微跌,今年以来升值0.48%