day 66 图论part03 101.孤岛的总面积 102.沉没孤岛 103.水流问题 104.建造最大岛屿

101.孤岛的总面积 

本题使用dfs,bfs,并查集都是可以的。

本题要求找到不靠边的陆地面积,那么我们只要从周边找到陆地然后 通过 dfs或者bfs 将周边靠陆地且相邻的陆地都变成海洋,然后再去重新遍历地图 统计此时还剩下的陆地就可以了。

import java.util.*;
import java.lang.Math.*;public class Main{public static void main(String[] args){Scanner scanner = new Scanner(System.in);int N = scanner.nextInt();int M = scanner.nextInt();int[][] grid = new int[N][M];for(int i = 0; i < N; i++){for(int j = 0; j < M; j++){grid[i][j] = scanner.nextInt();}}Solution solution = new Solution();System.out.println(solution.getSingle(grid, N, M));return;}}
class Solution{int[][] directions;Solution(){directions = new int[][]{{-1, 0}, {1, 0}, {0, 1}, {0, -1}};}int getSingle(int[][] grid, int N, int M){boolean[][] visited = new boolean[N][M];for(boolean[] v : visited){Arrays.fill(v, false);}int ans = -1;for(int i = 0; i < N; i++){for(int j = 0; j < M; j++){if(grid[i][j] == 1 && !visited[i][j]){ans = Math.max(ans, dfs(grid, visited, N, M, i, j));}}}return ans;}private int dfs(int[][] grid, boolean[][] visited, int N, int M, int i, int j){if(i < 0 || i >= N || j < 0 || j >= M || visited[i][j]){return 0;}visited[i][j] = true;if(grid[i][j] == 0){return 0;}if(grid[i][j] == 1 && (i == 0 || i == N - 1 || j == 0 || j == M - 1)){return -1;}int ret = 1;for(int k = 0; k < 4; k++){int rett = dfs(grid, visited, N, M, i + directions[k][0], j + directions[k][1]);if(rett == -1){ret = -1;}if(ret != -1){ret += rett;}}return ret;}
}

102.沉没孤岛

这道题目和0101.孤岛的总面积 (opens new window)正好反过来了,101.孤岛的总面积 (opens new window)是求 地图中间的空格数,而本题是要把地图中间的 1 都改成 0 。

思路依然是从地图周边出发,将周边空格相邻的陆地都做上标记,然后在遍历一遍地图,遇到 陆地 且没做过标记的,那么都是地图中间的 陆地 ,全部改成水域就行。

步骤一:深搜或者广搜将地图周边的 1 (陆地)全部改成 2 (特殊标记)

步骤二:将水域中间 1 (陆地)全部改成 水域(0)

步骤三:将之前标记的 2 改为 1 (陆地)

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int m = scanner.nextInt();int n = scanner.nextInt();int[][] island = new int[m][n];for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {island[i][j] = scanner.nextInt();}}handle(island);for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {System.out.print(island[i][j] + " ");}System.out.println("");}}private static final int[][] dirs = new int[][]{{0, 1}, {0, -1}, {1, 0}, {-1, 0}};private static void handle(int[][] island) {int m = island.length;int n = island[0].length;int x, y;x = 0;for (int j = 0; j < n; j++) {y = j;if (1 == island[x][y]) {dfs(island, x, y);}}x = m - 1;for (int j = 0; j < n; j++) {y = j;if (1 == island[x][y]) {dfs(island, x, y);}}y = 0;for (int i = 0; i < m; i++) {x = i;if (1 == island[x][y]) {dfs(island, x, y);}}y = n - 1;for (int i = 0; i < m; i++) {x = i;if (1 == island[x][y]) {dfs(island, x, y);}}for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (2 == island[i][j]) {island[i][j] = 1;} else if (1 == island[i][j]) {island[i][j] = 0;}}}}private static void dfs(int[][] island, int x, int y) {island[x][y] = 2;for (int[] dir : dirs) {int nx = x + dir[0];int ny = y + dir[1];if (nx < 0 || nx >= island.length || ny < 0 || ny >= island[0].length) {continue;}if (1 == island[nx][ny]) {dfs(island, nx, ny);}}}}

103.水流问题

一个比较直白的想法,其实就是 遍历每个点,然后看这个点 能不能同时到达第一组边界和第二组边界。

至于遍历方式,可以用dfs,也可以用bfs,以下用dfs来举例。

import com.sun.org.apache.xpath.internal.operations.Neg;import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;public class Main {static int[][] dirs = {{1,0},{-1,0},{0,1},{0,-1}};public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt(); // rowint m = sc.nextInt(); // colint[][] graph = new int[n][m];for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {graph[i][j] = sc.nextInt();}}boolean[][] canReachFirstGroup = new boolean[n][m];boolean[][] canReachSecondGroup = new boolean[n][m];// 从第一组边界出发进行DFSfor (int i = 0; i < n; i++) {dfs(graph, canReachFirstGroup, i, 0);}for (int j = 0; j < m; j++) {dfs(graph, canReachFirstGroup, 0, j);}// 从第二组出发进行DFSfor (int i = 0; i < n; i++) {dfs(graph, canReachSecondGroup, i, m - 1);}for (int j = 0; j < m; j++) {dfs(graph, canReachSecondGroup, n - 1, j);}// 找出同时可以到达两组边界的单元格for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (canReachFirstGroup[i][j] && canReachSecondGroup[i][j]){System.out.printf("%d %d\n",i ,j);}}}}private static void dfs(int[][] graph, boolean[][] canReach, int i, int j) {int n = graph.length;int m = graph[0].length;canReach[i][j] = true;for (int[] dir : dirs) {int newX = dir[0] + i;int newY = dir[1] + j;if (newX >= 0 && newX < n && newY >= 0 && newY < m && !canReach[newX][newY] && graph[newX][newY] >= graph[i][j]) {dfs(graph, canReach, newX, newY);}}}}

优化

#include <iostream>
#include <vector>
using namespace std;
int n, m;
int dir[4][2] = {-1, 0, 0, -1, 1, 0, 0, 1};
void dfs(vector<vector<int>>& grid, vector<vector<bool>>& visited, int x, int y) {if (visited[x][y]) return;visited[x][y] = true;for (int i = 0; i < 4; i++) {int nextx = x + dir[i][0];int nexty = y + dir[i][1];if (nextx < 0 || nextx >= n || nexty < 0 || nexty >= m) continue;if (grid[x][y] > grid[nextx][nexty]) continue; // 注意:这里是从低向高遍历dfs (grid, visited, nextx, nexty);}return;
}int main() {cin >> n >> m;vector<vector<int>> grid(n, vector<int>(m, 0));for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {cin >> grid[i][j];}}// 标记从第一组边界上的节点出发,可以遍历的节点vector<vector<bool>> firstBorder(n, vector<bool>(m, false));// 标记从第一组边界上的节点出发,可以遍历的节点vector<vector<bool>> secondBorder(n, vector<bool>(m, false));// 从最上和最下行的节点出发,向高处遍历for (int i = 0; i < n; i++) {dfs (grid, firstBorder, i, 0); // 遍历最左列,接触第一组边界dfs (grid, secondBorder, i, m - 1); // 遍历最右列,接触第二组边界}// 从最左和最右列的节点出发,向高处遍历for (int j = 0; j < m; j++) {dfs (grid, firstBorder, 0, j); // 遍历最上行,接触第一组边界dfs (grid, secondBorder, n - 1, j); // 遍历最下行,接触第二组边界}for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {// 如果这个节点,从第一组边界和第二组边界出发都遍历过,就是结果if (firstBorder[i][j] && secondBorder[i][j]) cout << i << " " << j << endl;;}}}

104.建造最大岛屿

本题的一个暴力想法,应该是遍历地图尝试 将每一个 0 改成1,然后去搜索地图中的最大的岛屿面积。

计算地图的最大面积:遍历地图 + 深搜岛屿,时间复杂度为 n * n。

(其实使用深搜还是广搜都是可以的,其目的就是遍历岛屿做一个标记,相当于染色,那么使用哪个遍历方式都行,以下我用深搜来讲解)

每改变一个0的方格,都需要重新计算一个地图的最大面积,所以 整体时间复杂度为:n^4。

import java.util.Arrays;
import java.util.Map;
import java.util.Scanner;// 逆向思维
public class Main {static int[][] dirs = {{1,0},{-1,0},{0,1},{0,-1}};static int ans = 0, area = 1;static boolean[][] visited;public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt(); // rowint m = sc.nextInt(); // colint[][] graph = new int[n][m];for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {graph[i][j] = sc.nextInt();}}boolean flag  = false;// 遍历for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {area = 1;visited = new boolean[n][m];if (graph[i][j] == 0){dfs(i, j, graph, n, m);flag = true;}}}System.out.println(flag ? ans : n * m);}private static void dfs(int row, int col, int[][] graph, int n, int m) {ans = Math.max(ans, area);visited[row][col] = true;for (int[] dir : dirs) {int newX = dir[0] + row;int newY = dir[1] + col;if(newX >= 0 && newX < n && newY >= 0 && newY < m && graph[newX][newY] == 1 && !visited[newX][newY]){area++;dfs(newX,newY,graph,n,m);}}}}

优化思路

其实每次深搜遍历计算最大岛屿面积,我们都做了很多重复的工作。

只要用一次深搜把每个岛屿的面积记录下来就好。

第一步:一次遍历地图,得出各个岛屿的面积,并做编号记录。可以使用map记录,key为岛屿编号,value为岛屿面积

第二步:再遍历地图,遍历0的方格(因为要将0变成1),并统计该1(由0变成的1)周边岛屿面积,将其相邻面积相加在一起,遍历所有 0 之后,就可以得出 选一个0变成1 之后的最大面积。

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

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

相关文章

【NOI】C++程序结构入门之嵌套循环一

文章目录 前言一、嵌套循环1.概念2.语法2.1 for循环嵌套for2.2 while循环嵌套for2.3 while循环嵌套while2.4for循环嵌套while2.5 注意2.5.1内层循环之前2.5.2内层循环之后 3.按位检查 二、例题讲解问题&#xff1a;1448. 随机体能测试问题&#xff1a;1469. 数的统计问题&#…

vue中图谱关系插件relation-graph

vue中图谱关系插件relation-graph 一、效果图二、安装下载&#xff08;vue2.0版本的&#xff09;三、直接上代码 一、效果图 二、安装下载&#xff08;vue2.0版本的&#xff09; npm install --save relation-graph var foo bar;三、直接上代码 <template><div cla…

基于 imx6ull 平台使用opencv4.7.0处理图片

本章节是针对opencv-4.7.0移植到 linux imx6ull系统&#xff0c;运行在Linux上&#xff0c;详细的移植流程请参考前面针对imx6ull平台移植opencv4.7.0&#xff0c;主要是针对应用开发&#xff0c;主要是对图片显示、旋转、缩放、显示字幕等应用场景开发。 二、环境要求 2.1 硬…

el-input 格式化输入值

1. 只允许输入数字&#xff0c;并保留两位小数<el-inputclass"config-input"type"number"v-model"v.minHeight"placeholder"":min"0"input"v.minHeight Number(Number(v.minHeight).toFixed(2))"/ 2. 只允许输…

半导体厂车间内如何实施等级保护

等级保护,全称为信息安全等级保护,是指根据信息系统在国家安全、经济建设、社会生活中的重要程度,以及信息系统一旦遭受破坏可能带来的影响和危害程度,对信息系统进行分等级保护的一种制度。在中国,等级保护通常分为五个等级,每个等级都有相应的保护要求和标准。 对于生…

【从0实现React18】 (五) 初探react mount流程 完成核心递归流程

更新流程的目的&#xff1a; 生成wip fiberNode树标记副作用flags 更新流程的步骤&#xff1a; 递&#xff1a;beginWork归&#xff1a;completeWork 在 上一节 &#xff0c;我们探讨了 React 应用在首次渲染或后续更新时的整体更新流程。在 Reconciler 工作流程中&#xff…

LLC开关电源开发:LLC设计参考文档(模态分析)

电源简析和全桥LLC模型分析 1.1模拟电源、开关电源和数字电源简介 1.1.1 模拟电源 模拟电源&#xff1a;即变压器电源&#xff0c;通过铁芯、线圈来实现&#xff0c;线圈的匝数决定了两端的电压比&#xff0c;铁芯的作用是传递变化磁场&#xff0c;&#xff08;我国&#xff09…

C语言——关键字 static volatile const extern 用法

static 不污染内存空间 用法&#xff1a; static void helperFunction() {// 实现细节 } /*在函数声明前加上"static"关键字可以将函数的作用域限制在当前源文件中。静态函数只能在当前源文件中调用&#xff0c;不能被其他源文件调用。使用静态函数有助于隐藏实现细…

摒弃反模式:使用Kotlin委托优化Android BaseActivity

摒弃反模式&#xff1a;使用Kotlin委托优化Android BaseActivity 在Android开发中&#xff0c;许多开发者习惯于创建名为“BaseActivity”或“BaseFragment”的基类&#xff0c;以便在所有Activity或Fragment中共享一些通用行为。这种方法乍一看似乎是个好主意&#xff0c;但实…

用Python制作幸运大转盘,抽奖转盘对比-tkinter(Python的内置GUI库)和pygame(一个更强大的游戏和多媒体应用库)——小白也能轻松看懂

一、要制作一个幸运大转盘&#xff08;抽奖转盘&#xff09;的Python程序&#xff0c;你可以使用图形库如tkinter&#xff08;Python的内置GUI库&#xff09;或者pygame&#xff08;一个更强大的游戏和多媒体应用库&#xff09;。由于tkinter更为简单和直接&#xff0c;以下是一…

零基础女生如何入门人工智能,从哪里下手?学习时间大概要多久?

作为一个理工科早期毕业生&#xff0c;出于近乎本能的敏感&#xff0c;格外关注全网热议的ChatGPT。 本来国内就业环境就不好&#xff0c;各行各业内卷越来越严重&#xff0c;加上人工智能的异军突起&#xff0c;各行各业势必将迎来科技进步跨时代的巨大冲击&#xff0c;在此情…

000005 - HDFS 读写流程

HDFS 读写流程 1 HDFS 写数据流程1.1 HDFS 写数据流程图1.2 HDFS 写数据之网络拓扑 - 节点距离计算1.3 机架感知&#xff08;副本存储节点选择&#xff09; 2 HDFS 读数据流程2.1 HDFS 读数据流程图 3 HDFS 如何做到机架感知 1 HDFS 写数据流程 1.1 HDFS 写数据流程图 &#x…

【代码随想录刷题】day02——977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II

977.有序数组的平方 方法一&#xff1a;暴力法 class Solution { public:vector<int> sortedSquares(vector<int>& nums) {// 暴力法for(int i 0; i < nums.size(); i){nums[i] * nums[i];}sort(nums.begin(), nums.end());return nums;} };方法二&#…

安美数字酒店宽带运营系统——命令执行漏洞(CNVD-2021-37784)

声明&#xff1a;本文档或演示材料仅供教育和教学目的使用&#xff0c;任何个人或组织使用本文档中的信息进行非法活动&#xff0c;均与本文档的作者无关。 文章目录 漏洞描述漏洞复现测试工具 漏洞描述 安美数字酒店宽带运营系统 server_ping.php 存在远程命令执行漏洞&#…

Spring RestTemplate配置DNS解析超时

RestTemplate 常用的超时设置方法可以设置连接超时、接口请求超时、接口响应超时&#xff0c;但是对于DNS解析超时往往没有简单的方法可以设置。本文介绍设置DNS解析超时时间的方法&#xff0c;具体的代码参照 示例项目 https://github.com/qihaiyan/springcamp/tree/master/sp…

2-15 基于matlab的蚁群,模拟退火,遗传,神经网络,禁忌搜索等智能优化算法对TSP问题

基于matlab的蚁群&#xff0c;模拟退火&#xff0c;遗传&#xff0c;神经网络&#xff0c;禁忌搜索等智能优化算法对TSP问题。五种优化算法对多个城市路径进行规划&#xff0c;通过优化速度、距离可比较五种方法的优劣。程序已调通&#xff0c;可直接运行。 2-15 蚁群优化算法 …

智能屏幕人体雷达感应开关模块,飞睿智能低功耗毫米波雷达技术,让冰箱更节能

在智能家居日益普及的今天&#xff0c;各种创新技术层出不穷&#xff0c;极大地提升了人们的生活品质。其中&#xff0c;人体雷达感应开关模块作为一种创新的传感器技术&#xff0c;正在逐步改变我们对家电设备的传统认知。本文将深入探讨飞睿智能人体雷达感应开关中的毫米波雷…

qml自定义组件

不管是component还是分文件编写的一个自定义组件&#xff0c;遵循如下&#xff1a; a:不管哪一级的子对象 都可以直接调根节点下的方法和属性 b:不管哪一级的子对象 调用非根节点的方法和属性&#xff0c;前面要加上该节点的id,即id.方法()或id.属性的形式 import QtQuick 2.…

使用插件和微调优化 GPT 模型

文章目录 LLM 用例和示例产品警惕 AI 幻觉&#xff1a;限制与考虑使⽤插件和微调优化 GPT 模型 OpenAI 在其网站上展示了许多激励人心的客户故事&#xff0c;我们需要了解这些模型如何改变我们的社会并为商业和创造力开辟新机遇。正如你将看到的&#xff0c;许多企业已经开始使…

web学习笔记(六十七)项目总结

目录 1.使用弹性布局来实现元素水平垂直居中 2. 实现vant组件样式穿透 3.通过请求返回的数据动态设置类名 4.设置元素溢出隐藏为省略号 5. z-index的使用 6.利用弹性布局实现横向滚动 7.盒子内的两个元素无法实现底部对齐 8.如何设置文本显示两行&#xff0c;且在第二行结…