【代码随想录Day51】图论Part03

孤岛的总面积

题目链接/文章讲解:代码随想录

import java.util.Scanner;

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();
            }
        }

        // 计算所有孤岛的总面积
        int totalArea = totalAreaOfIslands(grid);

        // 输出结果
        System.out.println(totalArea);
    }

    // 计算所有孤岛的总面积
    public static int totalAreaOfIslands(int[][] grid) {
        int total_area = 0; // 初始化孤岛总面积为0

        // 遍历整个二维网格
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                // 如果当前格子是陆地(值为1)
                if (grid[i][j] == 1) {
                    // 使用深度优先搜索计算当前岛屿的面积,并检查是否为孤岛
                    int area = dfs(grid, i, j);
                    // 如果返回的面积大于0,说明是孤岛,累加到总面积中
                    if (area > 0) {
                        total_area += area;
                    }
                }
            }
        }

        return total_area; // 返回孤岛总面积
    }

    // 深度优先搜索方法,用于计算岛屿的面积并检查是否为孤岛
    public static int dfs(int[][] grid, int i, int j) {
        // 检查当前格子是否越界或是否是水域(值为0)
        if (i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] == 0) {
            return 0; // 如果是越界或水域,返回面积为0
        }

        // 检查当前格子是否接触到矩阵的边缘
        if (i == 0 || i == grid.length - 1 || j == 0 || j == grid[0].length - 1) {
            return -1; // 如果接触到边缘,返回-1表示该岛屿不是孤岛
        }

        grid[i][j] = 0; // 将当前格子标记为已访问(值设为0)

        // 递归计算当前格子上、下、左、右四个方向的岛屿面积
        int up = dfs(grid, i - 1, j); // 上
        int down = dfs(grid, i + 1, j); // 下
        int left = dfs(grid, i, j - 1); // 左
        int right = dfs(grid, i, j + 1); // 右

        // 如果任意一个方向的面积为-1,说明该岛屿不是孤岛
        if (up == -1 || down == -1 || left == -1 || right == -1) {
            return -1; // 返回-1表示该岛屿不是孤岛
        }

        // 返回当前格子的面积(1)加上四个方向的面积之和
        return 1 + up + down + left + right;
    }
}

沉没孤岛

题目链接/文章讲解:代码随想录

import java.util.Scanner;

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();
            }
        }

        // 沉没所有孤岛
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                // 如果当前格子是陆地(值为1)
                if (grid[i][j] == 1) {
                    // 使用深度优先搜索检查是否为孤岛,并沉没孤岛
                    if (dfs(grid, i, j, new boolean[N][M])) {
                        sinkIsland(grid, i, j);
                    }
                }
            }
        }

        // 输出沉没后的矩阵
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                System.out.print(grid[i][j] + " ");
            }
            System.out.println();
        }
    }

    // 深度优先搜索方法,用于检查岛屿是否为孤岛
    public static boolean dfs(int[][] grid, int i, int j, boolean[][] visited) {
        // 检查当前格子是否越界或是否是水域(值为0)
        if (i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] == 0) {
            return true; // 如果是越界或水域,返回true
        }

        // 检查当前格子是否接触到矩阵的边缘
        if (i == 0 || i == grid.length - 1 || j == 0 || j == grid[0].length - 1) {
            return false; // 如果接触到边缘,返回false表示该岛屿不是孤岛
        }

        // 如果当前格子已经访问过,返回true
        if (visited[i][j]) {
            return true;
        }

        visited[i][j] = true; // 将当前格子标记为已访问

        // 递归检查当前格子上、下、左、右四个方向的岛屿是否为孤岛
        boolean up = dfs(grid, i - 1, j, visited); // 上
        boolean down = dfs(grid, i + 1, j, visited); // 下
        boolean left = dfs(grid, i, j - 1, visited); // 左
        boolean right = dfs(grid, i, j + 1, visited); // 右

        // 如果任意一个方向的岛屿不是孤岛,返回false
        return up && down && left && right;
    }

    // 沉没孤岛的方法
    public static void sinkIsland(int[][] grid, int i, int j) {
        // 检查当前格子是否越界或是否是水域(值为0)
        if (i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] == 0) {
            return; // 如果是越界或水域,返回
        }

        grid[i][j] = 0; // 将当前格子标记为水域(值设为0)

        // 递归沉没当前格子上、下、左、右四个方向的岛屿
        sinkIsland(grid, i - 1, j); // 上
        sinkIsland(grid, i + 1, j); // 下
        sinkIsland(grid, i, j - 1); // 左
        sinkIsland(grid, i, j + 1); // 右
    }
}

水流问题

题目链接/文章讲解:代码随想录

import java.util.*;

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();
            }
        }

        // 初始化两个布尔矩阵
        boolean[][] canReachFirst = new boolean[N][M];
        boolean[][] canReachSecond = new boolean[N][M];

        // 从第一组边界开始进行 BFS
        bfs(grid, canReachFirst, true);

        // 从第二组边界开始进行 BFS
        bfs(grid, canReachSecond, false);

        // 找出在两个标记矩阵中都被标记为 True 的单元格
        List<int[]> result = new ArrayList<>();
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (canReachFirst[i][j] && canReachSecond[i][j]) {
                    result.add(new int[]{i, j});
                }
            }
        }

        // 输出结果
        for (int[] cell : result) {
            System.out.println(cell[0] + " " + cell[1]);
        }
    }

    // 广度优先搜索方法
    public static void bfs(int[][] grid, boolean[][] canReach, boolean isFirstGroup) {
        int N = grid.length;
        int M = grid[0].length;
        Queue<int[]> queue = new LinkedList<>();

        // 初始化队列,添加第一组或第二组边界的单元格
        if (isFirstGroup) {
            // 第一组边界:左边界和上边界
            for (int i = 0; i < N; i++) {
                queue.add(new int[]{i, 0});
                canReach[i][0] = true;
            }
            for (int j = 1; j < M; j++) {
                queue.add(new int[]{0, j});
                canReach[0][j] = true;
            }
        } else {
            // 第二组边界:右边界和下边界
            for (int i = 0; i < N; i++) {
                queue.add(new int[]{i, M - 1});
                canReach[i][M - 1] = true;
            }
            for (int j = 0; j < M - 1; j++) {
                queue.add(new int[]{N - 1, j});
                canReach[N - 1][j] = true;
            }
        }

        // 方向数组,表示上下左右四个方向
        int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

        // 开始 BFS
        while (!queue.isEmpty()) {
            int[] cell = queue.poll();
            int x = cell[0];
            int y = cell[1];

            // 遍历四个方向
            for (int[] dir : directions) {
                int newX = x + dir[0];
                int newY = y + dir[1];

                // 检查新位置是否越界
                if (newX >= 0 && newX < N && newY >= 0 && newY < M) {
                    // 检查新位置是否可以到达,并且高度不高于当前位置
                    if (!canReach[newX][newY] && grid[newX][newY] >= grid[x][y]) {
                        canReach[newX][newY] = true;
                        queue.add(new int[]{newX, newY});
                    }
                }
            }
        }
    }
}

建造最大岛屿

题目链接/文章讲解:代码随想录

import java.util.*;

public class Main {
    // 记录每个岛屿的面积
    static int islandArea;
    // 用于标记不同岛屿的编号
    static int islandMark;
    // 定义二维数组表示四个方位(上下左右)
    static int[][] directions = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};

    // 使用深度优先搜索(DFS)来标记岛屿并计算其面积
    public static void depthFirstSearch(int[][] grid, int x, int y, boolean[][] visited) {
        // 边界条件检查
        if (x < 0 || x >= grid.length || y < 0 || y >= grid[0].length) return;
        // 如果已经访问过或者是海水,直接返回
        if (visited[x][y] || grid[x][y] == 0) return;

        visited[x][y] = true; // 标记为已访问
        islandArea++; // 增加当前岛屿的面积计数
        grid[x][y] = islandMark; // 将岛屿标记为当前编号

        // 继续向四个方向搜索
        for (int[] direction : directions) {
            depthFirstSearch(grid, x + direction[0], y + direction[1], visited);
        }
    }

    public static void main(String[] args) {
        // 接收输入
        Scanner scanner = new Scanner(System.in);
        int rows = scanner.nextInt();
        int cols = scanner.nextInt();

        int[][] grid = new int[rows][cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                grid[i][j] = scanner.nextInt();
            }
        }

        // 初始化岛屿标记,从2开始(0表示海水,1表示岛屿)
        islandMark = 2;

        // 创建一个boolean数组来记录每个位置是否被访问过
        boolean[][] visited = new boolean[rows][cols];

        // 创建一个HashMap来记录每个岛屿的标记号和对应面积
        HashMap<Integer, Integer> islandSizes = new HashMap<>();

        // 创建一个HashSet用于判断某一水域周围是否存在不同标记的岛屿
        HashSet<Integer> adjacentIslandMarks = new HashSet<>();

        // 检查是否全是岛屿
        boolean isAllIsland = true;

        // 遍历二维数组进行DFS搜索,标记每个岛屿并记录其面积
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (grid[i][j] == 0) isAllIsland = false; // 发现海水
                if (grid[i][j] == 1) {
                    islandArea = 0; // 重置岛屿面积计数
                    depthFirstSearch(grid, i, j, visited); // 执行DFS
                    islandSizes.put(islandMark, islandArea); // 记录岛屿面积
                    islandMark++; // 更新岛屿标记
                }
            }
        }

        // 初始化结果变量
        int maxConnectedArea = 0;
        if (isAllIsland) maxConnectedArea = rows * cols; // 如果全是岛屿,直接设置为总面积

        // 计算每个水域周围相邻岛屿的面积之和
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (grid[i][j] == 0) { // 只检查水域
                    adjacentIslandMarks.clear(); // 清空临时存储的岛屿标记
                    int currentSize = 1; // 将当前位置视为岛屿开始,初始面积为1

                    // 检查四个方向
                    for (int[] direction : directions) {
                        int adjacentRow = i + direction[0];
                        int adjacentCol = j + direction[1];

                        // 边界条件检查
                        if (adjacentRow < 0 || adjacentRow >= rows || adjacentCol < 0 || adjacentCol >= cols) continue;
                        int adjacentMark = grid[adjacentRow][adjacentCol];

                        // 跳过已访问或未记录的岛屿
                        if (adjacentIslandMarks.contains(adjacentMark) || !islandSizes.containsKey(adjacentMark)) continue;

                        adjacentIslandMarks.add(adjacentMark); // 记录相邻岛屿
                        currentSize += islandSizes.get(adjacentMark); // 增加面积
                    }

                    maxConnectedArea = Math.max(maxConnectedArea, currentSize); // 更新最大面积
                }
            }
        }

        // 输出结果
        System.out.println(maxConnectedArea);
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

QT QDialog::exec()调用时清除部件所有焦点

最近在做项目时&#xff0c;遇到一个问题&#xff1a;在统信UOS系统编写的QT程序&#xff0c;其中进入某些页面时&#xff0c;或者显示模态窗时&#xff0c;按钮都会有一个焦点框&#xff0c;这个是不允许的&#xff0c;于是乎&#xff0c;开始了清理焦点的旅途。 一、清理QDia…

高速自爆穿梭无人机技术详解

高速自爆穿梭无人机技术是一种结合了高速飞行与自爆式攻击能力的先进无人机技术。以下是对该技术的详细解析&#xff1a; 一、技术特点 1. 高速飞行&#xff1a; 高速自爆穿梭无人机通常具备极高的飞行速度&#xff0c;如部分型号的速度可达到174公里/小时&#xff0c;甚至更…

五,Linux基础环境搭建(CentOS7)- 安装Kafka

Linux基础环境搭建&#xff08;CentOS7&#xff09;- 安装Kafka 大家注意以下的环境搭建版本号&#xff0c;如果版本不匹配有可能出现问题&#xff01; 一、Kafka下载及安装 Kafka是由Apache软件基金会开发的一个开源流处理平台&#xff0c;由Scala和Java编写。Kafka是一种高…

[ARC159D] LIS 2 题解

[ARC159D] LIS 2 题面&#xff1a; 题面翻译 给定 n n n 个操作&#xff0c;每次操作给出 l , r l,r l,r&#xff0c;并在 a a a 序列里依次添加 i ∈ [ l , r ] i\in[l,r] i∈[l,r]。 求最后 a a a 的最长上升子序列。 题目描述 数列 $ X $ があります。初め、$ X $ は空…

网络搜索引擎Shodan(1)

声明&#xff1a;学习视频来自b站up主 泷羽sec&#xff0c;如涉及侵权马上删除文章 感谢泷羽sec 团队的教学 视频地址&#xff1a;shodan(1)_哔哩哔哩_bilibili 本文主要讲解网络搜索引擎Shodan的一些用法&#xff08;host和search这两个命令&#xff09;。 Shodan 是一个网络…

Matlab学习02-matlab中的数据显示格式及符号变量

目录 一&#xff0c;关系运算和逻辑运算 二&#xff0c;变量 三&#xff0c;数据显示格式 四&#xff0c;符号运算 1&#xff0c;创建符号变量 2&#xff0c;数值矩阵转换成符号矩阵 一&#xff0c;关系运算和逻辑运算 在matlab中&#xff0c;只要数值不是 &#xff0…

jenkins下拉参数联动

需要安装Active Choices插件&#xff0c;官网地址&#xff1a; https://plugins.jenkins.io/uno-choice/ 安装完插件以后会出现Active Choices选项&#xff1a; 第一个参数&#xff1a; return ["dubbo-op-all-deployment1", "dubbo-op-all-deployment2",…

合并数组的两种常用方法比较

在 JavaScript 中&#xff0c;合并数组的两种常用方法是使用扩展运算符 (...) 和使用 push 方法。 使用扩展运算符 this.items [...this.items, ...data.items]; 优点&#xff1a; 易于理解&#xff1a;使用扩展运算符的语法非常直观&#xff0c;表达了“将两个数组合并成一个…

基于vue框架的的高校消防设施管理系统06y99(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;设备分类,设备信息,维修人员,报修信息,维修进度,院系,消防知识,培训记录,培训信息,备件信息,备件申请,派发信息,采购信息 开题报告内容 基于Vue框架的高校消防设施管理系统开题报告 一、项目背景与意义 随着高校规模的不断扩大和校园建…

基于Django+Python的房屋信息可视化及价格预测系统设计与实现(带文档)

项目运行 需要先安装Python的相关依赖&#xff1a;pymysql&#xff0c;Django3.2.8&#xff0c;pillow 使用pip install 安装 第一步&#xff1a;创建数据库 第二步&#xff1a;执行SQL语句&#xff0c;.sql文件&#xff0c;运行该文件中的SQL语句 第三步&#xff1a;修改源…

无人机喊话器详解!

喊话器材料 外壳常采用尼龙纤维增强材料&#xff0c;这种材料具有抗摔、抗震、轻便、灵活、质量稳定、操作简单等优点&#xff0c;能够满足不同场景的需求。 喊话范围 无人机喊话器的喊话范围主要取决于设备的型号、环境条件以及喊话器的性能参数。一般来说&#xff0c;无人…

【334】基于springboot的仓库管理系统

本科毕业设计论文 题目&#xff1a;仓库管理系统设计与实现 摘 要 信息内容数据从传统到当今&#xff0c;一直在改变&#xff0c;忽然互联网技术让传统信息内容管理见到划时代的黎明&#xff0c;由于传统信息内容管理从时效性、安全系数、可执行性等多个方面&#xff0c;碰到…

rsync算法原理

1. 简介 rsync是一种文件同步的工具&#xff0c;也是一种算法。 2. 算法原理 背景&#xff1a;计算机 α \alpha α 上有文件 a, 计算机 β \beta β上有文件b。要对这两个文件进行同步。 β \beta β将文件b分成大小为S字节的若干块&#xff0c;最后一份可能不足S字节对于b…

中小企业设备维护新策略:Spring Boot系统设计与实现

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

安灯系统助力汽车零部件工厂快速解决生产异常

在汽车零部件制造领域&#xff0c;高效的生产管理和快速解决异常情况是确保产品质量和生产进度的关键。而安灯系统的应用&#xff0c;正为汽车零部件工厂带来了全新的变革&#xff0c;助力其快速解决生产异常。 汽车零部件工厂的生产报工产线看板直观地反映出生产的各项关键数据…

Redis的RDB执行原理

引入‘页表’的概念 Linux里面每个进程都是无法直接操作物理内存的&#xff0c;每个进程只能用页表映射本进程的虚拟内存到物理内存的映射。 bgsave的时候&#xff0c;主进程会fork&#xff08;复制&#xff09;一个子进程&#xff0c;然后该过程仅仅复制了页表。复制页表的过程…

使用 ASP.NET Core 8.0 创建最小 API

构建最小 API&#xff0c;以创建具有最小依赖项的 HTTP API。 它们非常适合需要在 ASP.NET Core 中仅包括最少文件、功能和依赖项的微服务和应用。 本教程介绍使用 ASP.NET Core 生成最小 API 的基础知识。 在 ASP.NET Core 中创建 API 的另一种方法是使用控制器。 有关在最小 …

使用 pydub 的 AudioSegment 获取音频时长 - python 实现

通过使用 pydub 的 AudioSegment 获取音频时长&#xff0c;音频常用格式如 m4a,wav等。 安装 python 库&#xff1a; pip install pydub 获取 m4a 格式的音频时长代码如下&#xff0c;代码如下&#xff1a; #-*-coding:utf-8-*- # date:2024-10 # Author: DataBall - XIAN #…

【云效】阿里云云效:一站式DevOps平台介绍与使用教程(图文)附PPT

【云效】阿里云云效:一站式DevOps平台介绍与使用教程(图文) 云效费用企业管理项目协作代码管理自动流水线测试管理扩展资料附:PPT版文件下载参考资料: https://devops.aliyun.com/ 云效 阿里云一站式DevOps(持续交付)平台,项目数字化协作能效工具。 官方介绍: 云效,一…

bindService 流程学习总结

Context.bindServiceContextImpl.bindServiceCommonActivityManagerService.bindIsolatedService ActiveServices.bindIsolatedServiceretrieveServiceLocked 获取服务信息&#xff1b;bringUpServiceLocked 拉起服务startProcessLocked创建进程 (进程不存在时)realStartServi…