代码随想录训练营第五十二天 孤岛的总面积

news2024/9/23 9:30:43

第一题:孤岛的总面积

第二题:沉没孤岛

思路:

将所有在边界的岛屿所在的visited数组位置都置为true,剩下的visited[i][j] == true && grid[i][j] == 1的位置就是孤岛,将其置为1即可。

代码如下

#include <iostream>
#include <vector>
using namespace std;
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) {
    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 >= grid.size() || nexty < 0 || nexty >= grid[0].size()) continue;
        // 不符合条件,不继续遍历
        if (grid[nextx][nexty] == 0) continue;
        if(!visited[nextx][nexty] && grid[nextx][nexty] == 1)
            dfs (grid, visited, nextx, nexty);
    }
    return;
}

int main() {
    int n, m;
    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>> visited(n, vector<bool>(m, false));
    // 从左侧边,和右侧边 向中间遍历
    for (int i = 0; i < n; i++) {
        if (grid[i][0] == 1 && !visited[i][0]) dfs(grid, visited, i, 0);
        if (grid[i][m - 1] == 1 && !visited[i][m - 1]) dfs(grid, visited, i, m - 1);
    }
    // 从上边和下边 向中间遍历
    for (int j = 0; j < m; j++) {
        if (grid[0][j] == 1 && !visited[0][j]) dfs(grid, visited, 0, j);
        if (grid[n - 1][j] == 1 && !visited[n - 1][j]) dfs(grid, visited, n - 1, j);
    }
    
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            if(!visited[i][j] && grid[i][j] == 1){
                grid[i][j] = 0;
            }
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cout << grid[i][j] << " " ;
        }
        cout << endl;
    }
}

第三题:水流问题

思路:

从第一组边界上的节点逆流而上,将遍历过的节点都标记上,

同样从第二组边界的边上节点逆流而上,将遍历过的节点也标记上

然后两方都标记过的节点就是目标节点

#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;;
        }
    }


}

第四题:建造最大工岛

思路:

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

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

代码如下:

#include <iostream>
#include <vector>
#include <unordered_set>
#include <unordered_map>
using namespace std;
int n, m;
int count;

int dir[4][2] = {0, 1, 1, 0, -1, 0, 0, -1}; // 四个方向
void dfs(vector<vector<int>>& grid, vector<vector<bool>>& 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);
    }
}

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>> visited(n, vector<bool>(m, false)); // 标记访问过的点
    unordered_map<int ,int> gridNum;
    int mark = 2; // 记录每个岛屿的编号
    bool 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); // 将与其链接的陆地都标记上 true
                gridNum[mark] = count; // 记录每一个岛屿的面积
                mark++; // 记录下一个岛屿编号
            }
        }
    }
    if (isAllGrid) {
        cout << n * m << endl; // 如果都是陆地,返回全面积
        return 0; // 结束程序
    }

    // 以下逻辑是根据添加陆地的位置,计算周边岛屿面积之和
    int result = 0; // 记录最后结果
    unordered_set<int> visitedGrid; // 标记访问过的岛屿
    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][1]; // 计算相邻坐标
                    int nearj = j + dir[k][0];
                    if (neari < 0 || neari >= n || nearj < 0 || nearj >= m) continue;
                    if (visitedGrid.count(grid[neari][nearj])) continue; // 添加过的岛屿不要重复添加
                    // 把相邻四面的岛屿数量加起来
                    count += gridNum[grid[neari][nearj]];
                    visitedGrid.insert(grid[neari][nearj]); // 标记该岛屿已经添加过
                }
            }
            result = max(result, count);
        }
    }
    cout << result << endl;

}

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

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

相关文章

WiFi to Ethernet: 树莓派共享无线连接至有线网口,自动通过Captive Poartal网页登录认证

物联网开发系列&#xff1a;物联网开发之旅① WiFi to Ethernet: 树莓派共享无线连接至有线网口&#xff0c;自动通过Captive Poartal验证物联网开发番外篇之 Captive Portal验证原理 文章目录 背景实现工具实现细节一、将无线连接共享到以太网1. 配置静态IP地址2. 启用IP转发3…

Chainlit快速实现AI对话应用的聊天记录如何持久性保存

前言 Chainlit 可以设置聊天记录用户搜索和浏览过去的对话。 如何实现 要启用聊天历史记录,您需要启用: 数据持久性身份验证恢复对话 为了让用户继续持久对话,请使用cl.on_chat_resume 生命周期钩子 装饰器使用户能够继续对话。需要同时启用数据持久性和身份验证。 该…

day21(mysql用户创建与授权、角色创建)

1.环境准备 [rootmysql ~]# rm -rf /etc/my.cnf //清空/etc目录下的my.cnf [rootmysql ~]# yum -y remove mariadb //移除mariadb [rootmysql ~]# find / -name "*mysql*" -exec rm -rf {} \; //删除mysql所有遗留 文件 2.安装绿色mysql [rootmysql ~]# t…

安装svd模型

svd模型简介 Stable Video Diffusion模型基于潜在的视频扩散模型&#xff0c;通过在小型、高质量的视频数据集上插入时间层并进行微调&#xff0c;将传统的2D图像合成模型转化为生成视频模型。这种方法的优点在于&#xff0c;它能够生成高分辨率的视频&#xff0c;并且具有强大…

C++基础编程100题-034 OpenJudge-1.4-15 最大数输出

更多资源请关注纽扣编程微信公众号 http://noi.openjudge.cn/ch0104/15/ 描述 输入三个整数,输出最大的数。 输入 输入为一行&#xff0c;包含三个整数&#xff0c;数与数之间以一个空格分开。 输出 输出一行&#xff0c;包含一个整数&#xff0c;即最大的整数。 样例…

【AI】关于AI和手机

2011 年至2015 年期间&#xff0c;全球智能手机出货量年增长率均超过两位数&#xff0c;显示出强劲的市场需 求和快速扩张趋势。然而&#xff0c;自2016 年起&#xff0c;全球智能手机用户数量趋于饱和&#xff0c;换机周期也逐 渐变长&#xff0c;市场进入存量替换阶段&#x…

人工智能时代,程序员如何保持核心竞争力?

人工智能时代&#xff0c;程序员如何保持核心竞争力&#xff1f; 随着AIGC&#xff08;如chatgpt、midjourney、claude等&#xff09;大语言模型接二连三的涌现&#xff0c;AI辅助编程工具日益普及&#xff0c;程序员的工作方式正在发生深刻变革。有人担心AI可能取代部分编程工…

FreeRTOS基础入门——RTOS背景知识简介(一)

个人名片&#xff1a; &#x1f393;作者简介&#xff1a;嵌入式领域优质创作者&#x1f310;个人主页&#xff1a;妄北y &#x1f4de;个人QQ&#xff1a;2061314755 &#x1f48c;个人邮箱&#xff1a;[mailto:2061314755qq.com] &#x1f4f1;个人微信&#xff1a;Vir2025WB…

必备:2024年四大文件翻译神器盘点!

在现代社会&#xff0c;语言不再是交流的障碍&#xff0c;文件翻译工具的出现&#xff0c;让不同语言之间的信息传递变得轻松自如。以下是几款备受推崇的文件翻译工具&#xff0c;它们将助大家轻松应对各种语言挑战&#xff0c;提升工作效率。 在当今的职场环境中&#xff0c;…

有没有性价比高的蓝牙耳机推荐?盘点4款开放式耳机排行榜10强

那当然是开放式蓝牙耳机性价比高呀&#xff0c;说到开放式蓝牙耳机的性价比呢&#xff0c;那我们可以先了解它的价位&#xff0c;它的价位大致可以分为三个价位。 低价位区间&#xff08;499元以下&#xff09;&#xff1a; 这个价格区间的开放式耳机通常受成本限制&#xff…

使用Step Functions运行AWS Backup时必备的权限要点

引言 在尝试从Step Functions执行AWS Backup的按需备份时&#xff0c;我在权限方面遇到了一些困难。为了备忘&#xff0c;我将这些经验写成这篇文章。 概述 从Step Functions执行AWS Backup时&#xff0c;需要分配以下权限&#xff1a; AWS Backup相关权限 执行备份的权限…

培训第二十一天(mysql用户创建与授权、角色创建)

上午 1、环境准备 [rootmysql ~]# rm -rf /etc/my.cnf //清空/etc目录下的my.cnf[rootmysql ~]# yum -y remove mariadb //移除mariadb[rootmysql ~]# find / -name "*mysql*" -exec rm -rf {} \; //删除mysql所有遗留文件 2、安装mysql绿包 [rootmysql ~]…

c->c++(四):gtest

本文主要探讨gtest相关内容。 gtest安装 wget -O gtest.zip https://github.com/google/googletest/archive/refs/heads/main.zipunzip gtest.zipcd googletest-mainmkdir bulid && cd buildcmake .. && make && make install gtest API TEST/TEST…

MySQL update set语句中 逗号与and的区别

语法 以下是 UPDATE 命令修改 MySQL 数据表数据的通用 SQL 语法&#xff1a; UPDATE table_name SET column1 value1, column2 value2, ... WHERE condition; 参数说明&#xff1a; table_name 是你要更新数据的表的名称。column1, column2, ... 是你要更新的列的名称。v…

减速电机的减速比计算原理

今天因为看到减速电机的内部中有通过齿轮来增加扭矩的结构&#xff0c;想找点原理性的文章来看一下&#xff0c;奈何遍寻不得。故提笔于此记录&#xff0c;以备往后回看。 图1 减速电机的竖截面剖视图 减速比为64&#xff0c;我的理解是在初始的齿轮转一圈的时候&#xff0c;最…

单片机配网,继电器开关,广播

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

qt安装图文

1.下载 通过百度网盘分享的文件&#xff1a;qt安装图文 链接&#xff1a;https://pan.baidu.com/s/1lQtYYvuybibDkdrMlpKJOg 提取码&#xff1a;11u7 --来自百度网盘超级会员V3的分享 2.安装

C++ 几何算法 - 向量点乘,叉乘及其应用

一&#xff1a;点乘介绍 1. 向量点乘&#xff1a; 2. 向量点乘的性质&#xff1a; 3. 向量点乘公式&#xff1a; 4. 向量的点乘的属性&#xff1a; &#xff08;1&#xff09;&#xff1a;向量与自身做点乘&#xff0c;会得到向量长度的平方&#xff1a; &#xff08;2&#xf…

JVM系列 | 对象的消亡3——垃圾收集器的对比与实现细节

垃圾收集器 文章目录 各收集器简单对比收集器启动参数各收集器详细说明JDK 1.3 之前JDK 1.3 | SerialJDK 1.4 | ParNewJDK 1.4 | Parallel ScavengeJDK 5 | CMS 收集器JDK 7 | G1 各收集器简单对比 收集器名称出现时间淘汰时间目标采用技术线程数STW分代备注无名JDK 1.3之前JD…

Android 自定义View(一):View是什么?如何创建自定义view,自定义属性等

目录 1&#xff09;View是什么&#xff1f; 2&#xff09;View分类 3&#xff09;View的知识点 4&#xff09;View的工作流程是怎么样的&#xff1f; 5&#xff09;案例&#xff1a;如何自定义View&#xff1f;比如我们要实现一个输入框带有清除按钮的view 6&#xff09;疑问&…