蓝桥杯第3513题——岛屿个数

news2024/11/24 8:36:47

解答代码

解题思路全在代码注释中,本题作者使用bfs方式作答

import java.util.*;
//1:无需package
//2: 类名必须Main, 不可修改

public class Main {
 public static void main(String[] args) {
     Scanner scan = new Scanner(System.in);
	 //T组数据,遍历T次
     int T = scan.nextInt();
     for(int p = 0; p < T; p++){
	   //岛屿的行数、列数
       int M = scan.nextInt();
       int N = scan.nextInt();
	   //岛屿矩阵
       int[][] island = new int[M][N];
	   //每个点的访问性,如果visited为true,代表该点是已被探明的岛屿
       boolean[][] visited = new boolean[M][N];
	   //记录每个岛屿的第一个点
       ArrayList<Pair> firstPoints = new ArrayList<>();
	   //bfs所用的队列
       Queue<Pair> queue = new ArrayDeque<>();
       int ans = 0;
	   //岛屿的寻找,需要向四个方向寻找相邻点
       int[] dx = {0,1,0,-1};
       int[] dy = {1,0,-1,0};
	   //岛屿矩阵的录入
       for(int i = 0; i < M; i++){
    	   String s = scan.next();
    	   char[] arr = s.toCharArray();
    	   for(int j = 0; j < N; j++) {
    		   island[i][j] = arr[j] - '0';
    	   }
       }
       //bfs岛屿数量添加
       for(int i = 0; i < M; i++){
         for(int j = 0; j < N; j++){
           if(island[i][j] == 1 && visited[i][j] == false){
             ans++;
             Pair firstPoint = new Pair(i,j);
             firstPoints.add(firstPoint);
             queue.offer(firstPoint);
             visited[i][j] = true;
             while(!queue.isEmpty()){
               Pair pair = queue.poll();
               for(int k = 0; k < dx.length; k++){
                 int x = pair.x + dx[k];
                 int y = pair.y + dy[k];
                 if(x >= 0 && x < M && y >= 0 && y < N){
                   if(island[x][y] == 1 && visited[x][y] == false){
                     queue.offer(new Pair(x,y));
                     visited[x][y] = true;
                   }
                 }
               }
             }
           }
         }
       }
	   //根据遍历方式可知,每个岛屿的第一个点有这样的特性
	   //该点的左和上两个方向上一定是海,且一定不会有该点所在岛屿的其他点
	   //因此只需要从这两个方向上的海出发,bfs搜索其连接海
	   //如果搜索时海坐标能到边界,说明这个岛屿不属于其他岛屿的子岛屿

	   //海域搜索的方向,每个点只要8个方向有一个能出去,就不是别人的子岛
	   //为什么不是4个方向请参考样例2中的3号岛屿
       int[] dxSea = {-1,-1,-1,0,0,1,1,1};
       int[] dySea = {1,0,-1,1,-1,1,0,-1};

       //子岛的判断,遍历所有岛屿的第一个点
	   outer:
       for(Pair point : firstPoints) {
		   //海的被访问性记录,对于每个岛屿单独记录
           boolean[][] visitedSea = new boolean[M][N];
		   //如果某个岛的第一个节点本身就在边界,肯定不是子岛,不必判断
    	   if(point.x != 0 && point.x != M-1 && point.y != 0 && point.y != N-1) {
    		   queue.clear();
			   //从岛屿第一个点的上方开始搜索海域
    		   queue.offer(new Pair(point.x-1, point.y));
    		   while(!queue.isEmpty()) {
    			   Pair temp = queue.poll();
				   //每个海节点必定会出队,判断出队的节点性质即可
    			   if(temp.x == 0 || temp.y == 0 || temp.x == M-1 || temp.y == N-1) {
					   //如果有海节点到达边界,说明该岛不是子岛,直接处理下一个节点
					   continue outer;
    			   }
    			   for(int k = 0; k < dxSea.length; k++) {
    				   int x = temp.x + dxSea[k];
    				   int y = temp.y + dySea[k];
					   //如果目标节点不越界,并且不是岛屿节点,也不是被访问过的海节点
    				   if(x >= 0 && x < M && y >= 0 && y < N) {
        				   if(visited[x][y] == false) {
        					   if(visitedSea[x][y] == false) {
								   //将该节点入队,并标记访问过
        						   queue.offer(new Pair(x,y));
        						   visitedSea[x][y] = true;
        					   }
        				   }
    				   }
    			   }
    		   }
    		   queue.clear();
			   //从岛屿第一个点的左方开始搜索海域,内容同上
    		   queue.offer(new Pair(point.x, point.y-1));
    		   while(!queue.isEmpty()) {
    			   Pair temp = queue.poll();
    			   if(temp.x == 0 || temp.y == 0 || temp.x == M-1 || temp.y == N-1) {
					   continue outer;
    			   }
    			   for(int k = 0; k < dxSea.length; k++) {
    				   int x = temp.x + dxSea[k];
    				   int y = temp.y + dySea[k];
    				   if(x >= 0 && x < M && y >= 0 && y < N) {
        				   if(visited[x][y] == false) {
        					   if(visitedSea[x][y] == false) {
        						   queue.offer(new Pair(x,y));
        						   visitedSea[x][y] = true;
        					   }
        				   }
    				   }
    			   }
    		   }
			   //如果所有海节点已经搜索完了,没有找到出路到达边界,说明是子岛屿,岛屿数量-1
    		   ans--;
    	   }
       }
       System.out.println(ans);
     }
     //在此输入您的代码...
     scan.close();
 }
}

class Pair{
	int x;
	int y;
	public Pair(int x, int y){
	 this.x = x;
	 this.y = y;
	}
	@Override
	public String toString() {
		return "Pair [x=" + x + ", y=" + y + "]";
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1184716.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据库数据恢复——MongoDB数据库报错“错误1067”的数据恢复案例

MongoDB数据库介绍&#xff1a; MongoDB数据库是文档数据存储库&#xff0c;将文档存储在集合之中&#xff0c;不是像MySQL一样的关系型数据库。 MongoDB数据库是开源数据库&#xff0c;同时提供具有附加功能的商业版本。 MongoDB数据库中的数据是以键值对(key-value pairs)的形…

vite + electron引入itk报错

代码 import { readImageArrayBuffer } from itk-wasm console.log(readImageArrayBuffer)通过itk-wasm官网&#xff0c;创建新的项目vitevue&#xff08;vue2或者vue3&#xff09;&#xff0c;都没问题。加入electeon后包此错。通过排查&#xff0c;意外找到原因&#xff0c;…

短视频电商时代来临,除了抖音,快手,又一个短视频进军电商了!

大家好&#xff0c;我是电商糖果 是一个95后&#xff0c;现居河南郑州。 做电商行业有六年多的时间了&#xff0c;京东&#xff0c;闲鱼&#xff0c;天猫都搞过。 在2020年紧跟当时的电商风口&#xff0c;开始做短视频电商&#xff0c;几个合作人开了一家抖音小店。 因为当…

ElasticSearch的集群、节点、索引、分片和副本

Elasticsearch是面向文档型数据库&#xff0c;一条数据在这里就是一个文档。为了方便大家理解&#xff0c;我们将Elasticsearch里存储文档数据和关系型数据库MySQL存储数据的概念进行一个类比 ES里的Index可以看做一个库&#xff0c;而Types相当于表&#xff0c;Documents则相当…

SpringDataJpa(三)

七、Specifications动态查询 有时我们在查询某个实体的时候&#xff0c;给定的条件是不固定的&#xff0c;这时就需要动态构建相应的查询语句&#xff0c;在Spring Data JPA中可以通过JpaSpecificationExecutor接口查询。相比JPQL,其优势是类型安全,更加的面向对象。 import …

霍兰德职业兴趣测试,对职业选择是否有帮助?

人们不喜欢标新立异&#xff0c;喜欢墨守成规&#xff0c;这也是有一定道理的&#xff0c;因为以往的传统更稳妥更可靠。创新是需要承担一定的风险的&#xff0c;求职应聘也是一样&#xff0c;不过虽然时代的发展&#xff0c;招聘方式越来越多的新花样&#xff0c;应聘也变的越…

2023年Q3乳品行业数据分析(乳品市场未来发展趋势)

随着人们生活水平的不断提高以及对健康生活的追求不断增强&#xff0c;牛奶作为优质蛋白和钙的补充品&#xff0c;市场需求逐年增加。 今年Q3&#xff0c;牛奶乳品市场仍呈增长趋势。根据鲸参谋电商数据分析平台的相关数据显示&#xff0c;2023年7月-9月&#xff0c;牛奶乳品市…

【并发编程-2】JUC-1

Lock 互斥锁&#xff1a; 1、锁的可重入性&#xff1a; 当一个线程调用object.lock()获取到锁&#xff0c;进入临界区后&#xff0c;还可以再次调用object.lock()。 通常锁都应该设计为可重入&#xff0c;否则就会发生死锁。 比如synchronized就是可重入&#xff0c;在一个s…

大数据是什么?

1.什么是数据&#xff1f; 数据是什么&#xff1f;什么样的称之为数据呐&#xff1f;我想找个问题提出来&#xff0c;各位小伙伴一定会喷我&#xff0c;脸数据都不知道的还在写什么大数据&#xff1f;但是我们转身再想一想&#xff0c;数据&#xff0c;我们真的了解本质吗&…

5G边缘计算网关的功能及作用

5G边缘计算网关具有多种功能。 首先&#xff0c;它支持智能云端控制&#xff0c;可以通过5G/4G/WIFI等无线网络将采集的数据直接上云&#xff0c;实现异地远程监测控制、预警通知、报告推送和设备连接等工作。 其次&#xff0c;5G边缘计算网关可以采集各种数据&#xff0c;包…

虚拟机ping不通百度,SecureCRTPortable连接不上

虚拟机ping不通百度&#xff0c;SecureCRTPortable连接不上 文章目录 虚拟机ping不通百度&#xff0c;SecureCRTPortable连接不上1、打开虚拟网络编辑器2、更改设置3、NAT设置4、设置网关4、设置网关 cat /etc/sysconfig/network-scripts/ifcfg-ens33 TYPEEthernet PROXY_METHO…

Web Worker:JS多线程的伪解药?

前言 在前端开发领域&#xff0c;JavaScript 的单线程限制一直是一个难以忽视的挑战。当谈到解决JavaScript的单线程限制时&#xff0c;HTML5引入的Web Worker被普遍认为是一剂解药&#x1f48a;。同时&#xff0c;业界中大量的文章也是聚焦于讨论web worker的神奇力量。然而&…

Banana Pi BPI-M6开源硬件开发板介绍以及与 Raspberry Pi 5 的比较

Banana Pi BPI-M6 Banana Pi BPI-M6是Banana-Pi组织最新开发的一款类似于Raspberry Pi的单板计算机&#xff0c;具有相同的尺寸格式和相似的功能。 今天我想向您介绍这些功能&#xff0c;并将它们与新的 Raspberry 5 提供的功能进行一些比较。 Raspberry Pi是英国 Raspberry P…

Cesium教程(二十):动态加载图片

1、效果预览 备注: 箭头图片可以去这里下载:箭头下载地址 2、代码编写 创建容器 <div id="cesiumContainer" class="fullSize"

软件版本控制系统VCS工具——cvs vss svn git

版本控制 版本控制系统&#xff08;Version Control System&#xff0c;VCS&#xff09;是用于跟踪和管理源代码和文档的工具。可追踪和管理修改历史&#xff0c;包括修改的内容、时间、作者等信息。有助于团队协作、追踪变更、恢复历史版本等。VCS的主要目的是帮助团队协作开…

竞赛选题 深度学习机器视觉车道线识别与检测 -自动驾驶

文章目录 1 前言2 先上成果3 车道线4 问题抽象(建立模型)5 帧掩码(Frame Mask)6 车道检测的图像预处理7 图像阈值化8 霍夫线变换9 实现车道检测9.1 帧掩码创建9.2 图像预处理9.2.1 图像阈值化9.2.2 霍夫线变换 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分…

Pytest系列(16)- 分布式测试插件之pytest-xdist的详细使用

前言 平常我们功能测试用例非常多时&#xff0c;比如有1千条用例&#xff0c;假设每个用例执行需要1分钟&#xff0c;如果单个测试人员执行需要1000分钟才能跑完当项目非常紧急时&#xff0c;会需要协调多个测试资源来把任务分成两部分&#xff0c;于是执行时间缩短一半&#…

【gogogo专栏】golang并发编程

golang并发编程 并发编程的工具goroutine介绍协程管理器sync.WaitGroup channel介绍readChannel和writeChannelclose的用法select的用法 通讯示例总结 并发编程的工具 在golang中&#xff0c;并发编程是比较简单的&#xff0c;不像java中那么麻烦&#xff0c;golang天然的支持协…

便携式电能质量分析仪

产品简介 KDZD5000电能质量分析仪是我公司精心研制的现场测试的三相、多功能、智能化、人机操作简洁的综合型测试仪器。具有容易使用&#xff0c;超大液晶彩屏显示&#xff0c;高分辨率&#xff0c;中英文双语操作界面&#xff0c;防振结构外壳等特点。可同时测量4路电流&…

Cesium 展示——拖拽点移动相邻线也跟着更新

文章目录 需求分析1. 获取所要移动实体的 ID2. 移动点相邻线跟着更新移动3. 注意4. 其他需求 实现 拖拽点移动相邻线也跟着更新 拖拽前 点击拖拽 拖拽后 分析 1. 获取所要移动实体的 ID 在Cesium中获取指定(x, y)位置处的实体ID,你可以通过以下步骤实现: 首先,使用Cesi…