代码随想录Day66(图论Part03)

101.孤岛的总面积

题目:101. 孤岛的总面积 (kamacoder.com)

思路:无

答案
import java.util.Scanner;class Main {private static int N, M;private static int[][] grid;private static boolean[][] visited;private static boolean touchesEdge;public static void main(String[] args) {Scanner scanner = new Scanner(System.in);N = scanner.nextInt();M = scanner.nextInt();grid = new int[N][M];visited = new boolean[N][M];for (int i = 0; i < N; i++) {for (int j = 0; j < M; j++) {grid[i][j] = scanner.nextInt();}}int totalIslandArea = 0;for (int i = 0; i < N; i++) {for (int j = 0; j < M; j++) {if (grid[i][j] == 1 && !visited[i][j]) {touchesEdge = false;int islandArea = dfs(i, j);if (!touchesEdge) {totalIslandArea += islandArea;}}}}System.out.println(totalIslandArea);}private static int dfs(int x, int y) {if (x < 0 || x >= N || y < 0 || y >= M) {return 0;}if (grid[x][y] == 0 || visited[x][y]) {return 0;}if (x == 0 || x == N - 1 || y == 0 || y == M - 1) {touchesEdge = true;}visited[x][y] = true;int area = 1;area += dfs(x + 1, y);area += dfs(x - 1, y);area += dfs(x, y + 1);area += dfs(x, y - 1);return area;}
}
小结

在dfs里面需要判断岛屿时候接触边缘

102.沉没孤岛

题目:102. 沉没孤岛 (kamacoder.com)

思路:判断周围也没有岛屿,上下左右都没有,那就将当前位置变为0

尝试(标题4)
import java.util.Scanner;class Main{public static int m;public static int n;public static int[][] grid;public static boolean[][] visited;public static void main(String[] args){Scanner scanner = new Scanner(System.in);n = scanner.nextInt();m = scanner.nextInt();grid = new int[n][m];visited = new boolean[n][m];for(int i=0; i<n; i++){for(int j=0; j<m; j++){grid[i][j] = scanner.nextInt();}}for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (grid[i][j] == 1 && !visited[i][j]) {int area = dfs(i, j);if(area == 1) grid[i][j] = 0;}}}for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {System.out.print(grid[i][j]+" ");}System.out.println();}}private static int dfs(int i, int j) {if (i < 0 || i >= n || j < 0 || j >= m || grid[i][j] == 0 || visited[i][j]) {return 0;}visited[i][j] = true;int area = 1;  // 当前格子的面积为1// 上area += dfs(i - 1, j);// 下area += dfs(i + 1, j);// 左area += dfs(i, j - 1);// 右area += dfs(i, j + 1);return area;}
}
答案
import java.util.Scanner;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();}}// 从边缘开始标记所有与边缘相连的陆地for (int i = 0; i < N; i++) {if (grid[i][0] == 1) {dfs(grid, i, 0, N, M);}if (grid[i][M - 1] == 1) {dfs(grid, i, M - 1, N, M);}}for (int j = 0; j < M; j++) {if (grid[0][j] == 1) {dfs(grid, 0, j, N, M);}if (grid[N - 1][j] == 1) {dfs(grid, N - 1, j, N, M);}}// 将所有未标记的陆地(孤岛)沉没for (int i = 0; i < N; i++) {for (int j = 0; j < M; j++) {if (grid[i][j] == 1) {grid[i][j] = 0;} else if (grid[i][j] == 2) {grid[i][j] = 1;}}}// 输出结果矩阵for (int i = 0; i < N; i++) {for (int j = 0; j < M; j++) {System.out.print(grid[i][j] + " ");}System.out.println();}scanner.close();}// 深度优先搜索(DFS)函数private static void dfs(int[][] grid, int x, int y, int N, int M) {if (x < 0 || x >= N || y < 0 || y >= M || grid[x][y] != 1) {return;}grid[x][y] = 2; // 标记为非孤岛dfs(grid, x + 1, y, N, M);dfs(grid, x - 1, y, N, M);dfs(grid, x, y + 1, N, M);dfs(grid, x, y - 1, N, M);}
}
小结

先标记所有非孤岛,再沉没所有孤岛,再撤销所有非孤岛标记

103.水流问题

题目:103. 水流问题 (kamacoder.com)

思路:我需要找到最大的数字,然后再用dfs搜索?以每一个格子为中心,画一个十字,只要有朝向第一组边界和朝向第二组边界的递减数组即可,写一个函数,计算水流能否到达第一组边界,另一个函数计算水流能否到达第二组边界,两个函数返回均为true时,记录该坐标

尝试(超时)
import java.util.Scanner;
import java.util.ArrayList;
class Main{public static int N;public static int M;public static int[][] grid;public static void main(String[] args){Scanner scanner = new Scanner(System.in);N = scanner.nextInt();M = scanner.nextInt();grid = new int[N][M];ArrayList<int[]> dynamicArray = new ArrayList<>();for(int i=0; i<N; i++){for(int j=0; j<M; j++){grid[i][j] = scanner.nextInt();}}for(int i=0; i<N; i++){for(int j=0; j<M; j++){if(firstBoundary(i,j) && secondBoundary(i,j)){dynamicArray.add(new int[]{i,j});}}}// 输出动态数组中的内容for (int[] array : dynamicArray) {System.out.println(array[0] + " " + array[1]);}}public static boolean firstBoundary(int i,int j){boolean up = true;boolean left = true;for(int k=i; k>0; k--){if(grid[k][j]>grid[i][j]) up = false;}for(int k=j; k>0; k--){if(grid[i][k]>grid[i][j]) left = false;}return up|| left;}public static boolean secondBoundary(int i,int j){boolean down = true;boolean right = true;for(int k=i; k<N; k++){if(grid[k][j]>grid[i][j]) down = false;}for(int k=j; k<M; k++){if(grid[i][k]>grid[i][j]) right = false;}return down||right;}
}
答案
import java.util.ArrayList;
import java.util.Scanner;class Main {public static int N;public static int M;public static int[][] grid;public static boolean[][] canReachFirstBoundary;public static boolean[][] canReachSecondBoundary;public static void main(String[] args) {Scanner scanner = new Scanner(System.in);N = scanner.nextInt();M = scanner.nextInt();grid = new int[N][M];canReachFirstBoundary = new boolean[N][M];canReachSecondBoundary = new boolean[N][M];for (int i = 0; i < N; i++) {for (int j = 0; j < M; j++) {grid[i][j] = scanner.nextInt();}}// 从第一组边界开始反向DFSfor (int i = 0; i < N; i++) {dfs(i, 0, canReachFirstBoundary);dfs(i, M - 1, canReachSecondBoundary);}for (int j = 0; j < M; j++) {dfs(0, j, canReachFirstBoundary);dfs(N - 1, j, canReachSecondBoundary);}// 找出既能到达第一组边界又能到达第二组边界的单元格ArrayList<int[]> result = new ArrayList<>();for (int i = 0; i < N; i++) {for (int j = 0; j < M; j++) {if (canReachFirstBoundary[i][j] && canReachSecondBoundary[i][j]) {result.add(new int[]{i, j});}}}// 输出结果for (int[] cell : result) {System.out.println(cell[0] + " " + cell[1]);}}// 深度优先搜索(DFS)函数private static void dfs(int x, int y, boolean[][] canReach) {if (canReach[x][y]) {return;}canReach[x][y] = true;int[][] directions = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};for (int[] direction : directions) {int newX = x + direction[0];int newY = y + direction[1];if (newX >= 0 && newX < N && newY >= 0 && newY < M && grid[newX][newY] >= grid[x][y]) {dfs(newX, newY, canReach);}}}
}
小结

反向dfs效率更高

104.建造最大岛屿

题目:104. 建造最大岛屿 (kamacoder.com)

思路:感觉肯定是要找到最大的岛屿,再去连接,或者是第二大的,又或者是岛屿从大到小,都试一遍,逐个将岛屿的某个边缘变为陆地

这个1 肯定是出现在岛屿的边缘,或许我可以先遍历一遍,找到所有的边缘,

尝试(写不出来)
import java.util.Scanner;class Main{public static int N;public static int M;public static int[][] grid;public static boolean[][] visited;public static boolean flag;public static void main(String[] args){Scanner scan = new Scanner(System.in);N = scan.nextInt();M = scan.nextInt();grid = new int[N][M];for(int i=0; i<N; i++){for(int j=0; j<M; j++){grid[i][j] = scan.nextInt();}}// 遍历grid,找到所有的边缘,单元格每与一个陆地接触,就加1// 初始值为2,为了区分岛屿的1for(int i=0; i<N; i++){for(int j=0; j<M; j++){grid[i][j] = scan.nextInt();}}}public static void dfs(int i, int j){if(i<0 || i>=N || j<0 ||  j>=M){return;}visited[i][j] = true;if(grid[i][j]==1) flag = true;if(flag){if(grid[i][j]==0){grid[i][j] =2;}else{grid[i][j]+=1;}} dfs(i-1,j);dfs(i+1,j);dfs(i,j-1);dfs(i,j+1);}}
答案(卡码网上别人的,看不懂)
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);}}}}
答案(仿照代码随想录中C++的逻辑,运行错误)
import java.util.*;public class Main {static int n, m;static int count;static int[][] dir = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}}; // 四个方向public static void main(String[] args) {Scanner scanner = new Scanner(System.in);n = scanner.nextInt();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();}}boolean[][] visited = new boolean[n][m]; // 标记访问过的点,初始化为falseMap<Integer, Integer> gridNum = new HashMap<>();int mark = 2; // 记录每个岛屿的编号boolean isAllGrid = true; // 标记是否整个地图都是陆地// 计算每个岛屿的面积并标记for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (grid[i][j] == 0) isAllGrid = false;if (!visited[i][j] && grid[i][j] == 1) {count = 0;dfs(grid, visited, i, j, mark); // 将与其链接的陆地都标记上 truegridNum.put(mark, count); // 记录每一个岛屿的面积mark++; // 记录下一个岛屿编号}}}if (isAllGrid) {System.out.println(n * m); // 如果都是陆地,返回全面积return; // 结束程序}// 以下逻辑是根据添加陆地的位置,计算周边岛屿面积之和int result = 0; // 记录最后结果Set<Integer> visitedGrid = new HashSet<>(); // 标记访问过的岛屿for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {count = 1; // 记录连接之后的岛屿数量visitedGrid.clear(); // 每次使用时,清空if (grid[i][j] == 0) {for (int k = 0; k < 4; k++) {int neari = i + dir[k][0]; // 计算相邻坐标int nearj = j + dir[k][1];if (neari < 0 || nearj < 0 || neari >= n || nearj >= m) continue;if (visitedGrid.contains(grid[neari][nearj])) continue; // 添加过的岛屿不要重复添加// 把相邻四面的岛屿数量加起来count += gridNum.get(grid[neari][nearj]);visitedGrid.add(grid[neari][nearj]); // 标记该岛屿已经添加过}}result = Math.max(result, count);}}System.out.println(result);}// 深度优先搜索函数private static void dfs(int[][] grid, boolean[][] visited, int x, int y, int mark) {if (visited[x][y] || grid[x][y] == 0) return; visited[x][y] = true; // 标记访问过grid[x][y] = mark; // 给陆地标记新标签count++;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;dfs(grid, visited, nextx, nexty, mark);}}
}

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

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

相关文章

少见的更优写法,反转字符串中的元音字母

Leetcode 原题链接 解法一 这道题很简单&#xff0c;令双指针 l l l 和 r r r 从两侧相向移动&#xff0c;交换元音字母即可。但大多人的实现是如下这种可简化的嵌套循环。 如果是 Java 等 String 不可变的语言&#xff0c;应先转换为 CharArray&#xff0c;交换完元音字母…

数据库相关学习记录

oracle如何对A-数字-数字类型的字段进行排序 在Oracle中&#xff0c;如果你有一个字段&#xff0c;比如 A-数字-数字 的格式&#xff0c;并且你想要根据这样的格式对数据进行排序&#xff0c;你可以使用 REGEXP_SUBSTR 函数来提取并且转换字符串中的数字部分&#xff0c;然后进…

上海市计算机学会竞赛平台2023年5月月赛丙组滑雪训练

题目描述 小爱最近迷上了滑雪&#xff0c;某滑雪场有 &#x1d45b;n 条不同难度的雪道&#xff0c;只有学习并滑了第 &#x1d456;i 条雪道&#xff0c;才能去参加第 &#x1d456;1i1 条雪道的学习与训练。 已知&#xff0c;第一次滑第 &#x1d456;i 条雪道时&#xff0…

【shell】将txt文件拆成n个,文本均匀按行分布

#!/bin/bash # 原始文件名 source_file"/home/part.txt"# 目标文件存放目录 target_dir"/home"# 想要的近似文件数量 desired_files2 # 请将n替换为具体的数字&#xff0c;比如100# 确保目标目录存在 mkdir -p "$target_dir"# 计算原始文件的…

家用洗地机什么牌子好?四款公认品牌好的机型推荐

每个人都希望自己的家里面能够干干净净&#xff0c;就算不是一尘不染&#xff0c;也至少应该是整洁的&#xff0c;但是在这个快节奏的大环境下&#xff0c;做清洁对于人们来说&#xff0c;不是没时间&#xff0c;就是太累了。正当此时&#xff0c;一款造福懒人的神器——家用洗…

Double 4 VR虚拟仿真教学系统在商务英语课堂上的应用

随着科技的飞速发展&#xff0c;VR&#xff08;虚拟现实&#xff09;技术逐渐在教育领域展现出其独特的魅力。特别是在商务英语课堂上&#xff0c;Double 4 VR虚拟仿真教学系统正逐渐成为一种新颖而有效的教学工具。 一、Double 4 VR虚拟仿真教学系统的引入 在传统的商务英语…

4D 生物打印技术的挑战:从打印到植入,还有多远?

4D生物打印技术将时间维度融入生物打印&#xff0c;为构建具有动态特性和功能的生物组织结构提供了无限可能。然而&#xff0c;要实现这些目标&#xff0c;选择合适的生物打印技术至关重要。本文将详细介绍几种主要的4D生物打印技术&#xff0c;并分析它们各自的优缺点&#xf…

Linux—— 逻辑运算符,压缩和解压缩

- -a&#xff1a; and 逻辑与 - -o&#xff1a; or 逻辑或 - -not&#xff1a; not 逻辑非 - 优先级&#xff1a;与>或>非 shell [rootserver ~]# find / -size 10k -a -size -50k [rootserver ~]# find /etc -name "e*" -o -name "f*"…

前端初学java二(类、多态、接口、内部类、泛型)

目录 类 种类 Javabean类 测试类 工具类 类的初始化 构照函数 新建对象的内存图 static 继承 This Super 虚方法表 Override 修饰符权限 构造代码块 静态代码块 多态 前提 优点 缺点 示例 抽象方法 抽象类 接口 implements 继承 内部类 成员内部类…

centos7安装mysql教程及免费数据库视图软件

文章所有命令最好在根目录&#xff0c;并以root权限 执行 Mysql安装 1. 添加 MySQL Yum Repository MySQL 官方不再维护 CentOS 7 自带的 MySQL 软件包。你需要先下载并安装 MySQL Yum Repository。 sudo yum install https://dev.mysql.com/get/mysql80-community-release…

期末考试题-通过HTML编程Vue3选项式:简易购物车

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><!-- 引用 element-plus 样式 --><!-- 注意&#xff1a;复…

React+TS 从零开始教程(4):useEffect

上一节传送门&#xff1a;ReactTS 从零开始教程&#xff08;3&#xff09;&#xff1a;useState 源码链接&#xff1a;https://pan.quark.cn/s/c6fbc31dcb02 上一节&#xff0c;我们已经学会了React的第一个Hook&#xff1a;useState。 这一节&#xff0c;我们要学习的是另一…

C语言----文件操作

1.为什么使用文件&#xff1f; 如果没有⽂件&#xff0c;我们写的程序的数据是存储在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&#xff0c;数据就丢失了&#xff0c;等再次运⾏程序&#xff0c;是看不到上次程序的数据的&#xff0c;如果要将数据进⾏持久化…

Java语言开发的一套智慧产科系统源码:产科专科电子病历系统源码

Java语言开发的一套智慧产科系统源码&#xff1a;产科专科电子病历系统源码 系统概述 电子病历系统是以住院病人为中心&#xff0c;面向医生以及护士为主的&#xff0c;涉及临床治疗、护理等业务的临床信息系统&#xff0c;以电子信息技术为手段&#xff0c;实时采集病人在整个…

【每日一练】Python遍历循环

1. 情节描述&#xff1a;上公交车(10个座位)&#xff0c;并且有座位就可以坐下 要求&#xff1a;输入公交卡当前的余额&#xff0c;只要超过2元&#xff0c;就可以上公交车&#xff1b;如果车上有空座位&#xff0c;才可以上。 seat 10 while seat > 0:money int(input(…

cookie/session/token/jwt

Cookie 定义: Cookie 是服务器发送到用户浏览器并存储在本地的小型数据片段&#xff0c;用于在客户端存储会话信息。 Cookie是Web服务器发送给浏览器的一小段数据&#xff0c;浏览器之后在每次请求同一服务器时会将这段数据回传。Cookie的主要作用是维持用户状态&#xff0c;例…

分层解耦----

分层解耦 类聚 软件中各个功能模块内部的功能联系. 例如: 高类聚示例&#xff1a;想象一下餐厅的厨房&#xff0c;每个厨师负责自己的工作站&#xff0c;一个专门做沙拉&#xff0c;一个专门烤肉&#xff0c;另一个专门做甜点。每个工作站内的工作高度类聚&#xff0c;即每个…

vite项目如何在本地启动https协议

vite项目如何在本地启动https协议 本地启动正常配置在vite.config.js文件中默认启动http协议的请求&#xff0c;如何改成https呢&#xff1f;今天的开发中遇到了这个问题项目需求&#xff1a; 本地启动https协议的前端页面并且正常访问后台https协议的接口 解决方法&#xff1a…

private修饰的方法或属性能被子类继承嘛?

先说结论&#xff1a;能。 这是一个反直觉的问题&#xff0c;毕竟大家在学习阶段接收到的知识就是&#xff1a;被privaite修饰的方法和成员变量不能被继承。 证明过程可参考文档&#xff1a;private修饰的变量如何调用_你真的熟悉java继承关系&#xff1f;那你知道父类private…

Elasticsearch:Runtime fields - 运行时字段(二)

这是继上一篇文章 “Elasticsearch&#xff1a;Runtime fields - 运行时字段&#xff08;一&#xff09;” 的续篇。 在查询时覆盖字段值 如果你创建的运行时字段与映射中已存在的字段同名&#xff0c;则运行时字段会隐藏映射字段。在查询时&#xff0c;Elasticsearch 会评估运…