C语言编程题_3D接雨水

news2025/1/17 15:43:51

接雨水的题目描述如下。

(1) 2D接雨水: 字节员工是不是个个都会接雨水 ;

(2) 3D接雨水: 407. 接雨水 II ;

(3) 3D接雨水: 字节人都会的 3D接雨水 。

  问题描述

  难度:困难

  给你一个 m x n 的矩阵,其中的值均为非负整数,代表二维高度图每个单元的高度,请计算图中形状最多能接多少体积的雨水。

  示例1:

  输入:heightMap = [[1,4,3,1,3,2],[3,2,1,3,2,4],[2,3,3,2,3,1]];

  输出:4

  解释:下雨后,雨水将会上图蓝色的方块中。总的接雨水量为1+1+1=4。

  我找到的最好的思路是:把这个看成木桶接水,就像是短板理论。最外层一圈一定接不到水,也就是可以看成木桶的边缘,先把木桶的边缘都放进优先队列中,这时取出最小的柱子,向这个柱子的 4 个方向扩散,扩散出的柱子有两种情况,如果比当前柱子大,那么不能接水,如果比当前柱子小,那么接到的水就是当前柱子高度减去扩散柱子的高度(为什么?因为当前柱子一定是边缘最小的了,所以它一定能接到水),后面在把扩散的柱子加入到优先队列中,已经比较完的柱子就移出队列,这样就又形成了新的桶的边缘,并且水桶面积也在不断缩小(当然要记录走过的柱子,防止重复走),最终就会计算完成。

  下面是用C语言实现的3D接雨水:

#include <stdio.h>
#include <stdlib.h>

#define Cols            (6)
#define Rows            (3)

#define Status_ToDo     (0) // 待处理的。
#define Status_Done     (1) // 已处理的。
#define Status_Border   (2) // 作为木桶板。

int addRainWaterOfTBLR(int height[][Cols], int status[][Cols], int minBorderHeight, int row, int col);

void initStatus(int arr[][Cols]) {
    // // 注: 使用下面语句得到的rowCount为0, 因为arr作为形参的时候就会被当作一个指针。
    // int rowCount = sizeof(arr) / sizeof(arr[0]);
    for (int row = 0; row < Rows; row++) {
        for (int col = 0; col < Cols; col++) {
            if (0 == row || Rows-1 == row || 0 == col || Cols-1 == col) {
                arr[row][col] = Status_Border;
            } else {
                arr[row][col] = Status_ToDo;
            }
        }
    }
    // 去掉四个角。
    arr[0][0] = arr[0][Cols-1] = arr[Rows-1][0] = arr[Rows-1][Cols-1] = Status_Done;
}

void showStatus(int height[][Cols], int status[][Cols]) {
    printf("打印状态:\n");
    for (int row = 0; row < Rows; row++) {
        for (int col = 0; col < Cols; col++) {
            printf("%d(%d), ", height[row][col], status[row][col]);
        }
        printf("\n");
    }
}

void findPositionOfMinBorder(int height[][Cols], int status[][Cols], int result[2]) {
    // printf("findPositionOfMinBorder\n");
    result[0] = 0;
    result[1] = 0;
    for (int row = 0; row < Rows; row++) {
        for (int col = 0; col < Cols; col++) {
            if (Status_Border == status[row][col]
                && ((0 == result[0] && 0 == result[1]) || height[row][col] < height[result[0]][result[1]])
            ) {
                result[0] = row;
                result[1] = col;
            }
        }
    }
    printf("最小板的位置是(%d,%d)\n", result[0], result[1]);
}

void repairBorder(int status[][Cols]) {
    for (int row = 0; row < Rows; row++) {
        for (int col = 0; col < Cols; col++) {
            if (Status_Border == status[row][col]) {
                //上下左右都不是待处理的。
                if ((0 == row || (row > 0 && status[row-1][col] != Status_ToDo))
                    && (Rows-1 == row || (Rows-1 > row && status[row+1][col] != Status_ToDo))
                    && (0 == col || (col > 0 && status[row][col-1] != Status_ToDo))
                    && (Cols-1 == col || (Cols-1 > col && status[row][col+1] != Status_ToDo))
                ) {
                    status[row][col] = Status_Done;
                }
            }
        }
    }
}

int addRainWaterAtPosition(int height[][Cols], int status[][Cols], int minBorderHeight, int row, int col) {
    int result = 0;
    // printf("addRainWaterAtPosition(%d,%d)\n", row, col);
    if (height[row][col] <= minBorderHeight) {
        result += (minBorderHeight - height[row][col]);
        result += addRainWaterOfTBLR(height, status, minBorderHeight, row, col);
    } else {
        status[row][col] = Status_Border;
    }
    return result;
}

int addRainWaterOfTBLR(int height[][Cols], int status[][Cols], int minBorderHeight, int row, int col) {
    int result = 0;
    // printf("addRainWaterOfTBLR(%d,%d)\n", row, col);
    status[row][col] = Status_Done;
    if (row > 0 && Status_ToDo == status[row-1][col]) { // 上。
        result += addRainWaterAtPosition(height, status, minBorderHeight, row-1, col);
    }
    if (row < Rows-1 && Status_ToDo == status[row+1][col]) { // 下。
        result += addRainWaterAtPosition(height, status, minBorderHeight, row+1, col);
    }
    if (col > 0 && Status_ToDo == status[row][col-1]) { // 左。
        result += addRainWaterAtPosition(height, status, minBorderHeight, row, col-1);
    }
    if (col < Cols-1 && Status_ToDo == status[row][col+1]) { // 右。
        result += addRainWaterAtPosition(height, status, minBorderHeight, row, col+1);
    }
    return result;
}

// 判断完成。
int checkFinish(int status[][Cols]) {
    for (int row = 0; row < Rows; row++) {
        for (int col = 0; col < Cols; col++) {
            if (Status_ToDo == status[row][col]) {
                return 0;
            }
        }
    }
    return 1;
}

// 简介:  3D接雨水。
int main(void)
{
    int rainWater = 0;
    int heightMap[][Cols] = {{1,4,3,1,3,2},{3,2,1,3,2,4},{2,3,3,2,3,1}};
    // printf("heightMap_rowCount = %d。\n", sizeof(heightMap) / sizeof(heightMap[0]));
    int (*status)[Cols] = malloc(sizeof(int) * (sizeof(heightMap) / sizeof(heightMap[0])) * Cols);
    initStatus(status);
    showStatus(heightMap, status);

    while(!checkFinish(status)) {
        int positionOfMinBorder[2] = {0, 0};
        findPositionOfMinBorder(heightMap, status, positionOfMinBorder);
        int minBorderHeight = heightMap[positionOfMinBorder[0]][positionOfMinBorder[1]];
        // printf("minBorderHeight=%d\n", minBorderHeight);
        rainWater += addRainWaterOfTBLR(heightMap, status, minBorderHeight, positionOfMinBorder[0], positionOfMinBorder[1]);
        repairBorder(status);
        showStatus(heightMap, status);
    }
    printf("总的接雨水量为%d\n", rainWater);

    free(status);

    printf("程序正常退出。\n");
    return 0;
}

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

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

相关文章

【历史版本火狐浏览器下载】

历史版本火狐浏览器下载 介绍 火狐浏览器是一款开源的互联网浏览器&#xff0c;由Mozilla基金会开发。它的历史版本可以追溯到2002年&#xff0c;以下是一些重要的历史版本介绍&#xff1a; Firefox 1.0&#xff08;2004年&#xff09;- 这是火狐浏览器的第一个正式版本&…

安装多个MySQL版本时如何连接到不同的数据库

当安装多个版本的数据库时&#xff0c;不同版本的端口名不一样&#xff0c;可以使用以下命令进行连接 mysql -uroot -p数据库密码 -h主机名 -P端口号 数据库主机名默认是localhost&#xff0c;端口号默认是3306&#xff0c;当安装多个版本数据库时&#xff0c;需要记住数据库的…

vim+xxd 编辑16进制

1. vim -b mib 2. 在vim 中执行 %!xxd, 这样就可以输入16进制&#xff1a; 3. 输入完成后&#xff0c;在vim中 执行 %!xxd -r 切换至原模式&#xff1b; 4. 保存退出即可 5. 重新打开mib文件&#xff1a;vim -b mib 6. 在vim 中执行 %!xxd, 查看是否符合预期&#xff1a;…

java 语法中的数据类型

Java有哪些数据类型&#xff1f; Java语言数据类型分为两种&#xff1a;基本数据类型和引用数据类型。 Java基本数据类型范围和默认值&#xff1a; 需要注意一下&#xff0c;对于布尔类型&#xff1a; 如果 boolean 是单独使用&#xff08;在编译之后使用 Java 虚拟机中的 int…

民航电子数据库:报错merge sql error, dbType null, druid-1.1.9, sql : xxx

目录 一、场景二、SQL三、报错信息四、排查五、原因六、解决 一、场景 1、对接民航电子数据库 2、limit查询时报错 二、SQL SELECT openid,headimgurl,nickname FROM t_mb_weixinuser WHERE openid? AND vdnId ? LIMIT 1三、报错信息 merge sql error, dbType null, dru…

一觉醒来 AI科技圈发生的大小事儿 04月24日

该日报由AI生成&#xff0c;制作方法联系 【微信:wenhaofree】 ⏩昆仑万维23年收入49亿净利润13亿&#xff0c;研发费用增长40%&#xff0c;坚定All in AGI与AIGC 昆仑万维发布2023年年度业绩报告&#xff0c;实现营业收入49.2亿元&#xff0c;净利润12.6亿元&#xff0c;同比…

学习Rust的第17天:Traits

Rust traits&#xff0c;包括自定义trait声明&#xff0c;trait边界&#xff0c;实现trait的返回类型&#xff0c;条件方法实现和blanket实现。Rust的多态性严重依赖于traits&#xff0c;这允许基于trait的分派和泛型编程。掌握traits使开发人员能够创建灵活的、可维护的代码&a…

Unity射线实现碰撞检测(不需要rigbody组件)

使用physic.CapsulCast&#xff08;&#xff09;&#xff1b; 前面3个参数生成一个胶囊体&#xff0c; 向着发射方向&#xff0c;发射出一串的胶囊&#xff08;没有最大距离&#xff09; 有最大距离&#xff0c;可以节约性能开销。 physic.CapsulCast&#xff08;&#xff0…

BUUCTF---misc---[ACTF新生赛2020]outguess

1、下载附件&#xff0c;解压之后得到下面信息 2、查看图片属性&#xff0c;发现有个核心价值观编码&#xff1b;解码为abc 3、flag.txt提示 4、结合题目&#xff0c;这是一个outguess隐写 5、用kali先下载安装隐写库 6、使用命令-k(密钥)&#xff1b;-r(将图片里面的隐写信息…

数据结构练习-线性表定义与基本操作

----------------------------------------------------------------------------------------------------------------------------- 1. 线性表是( )。 A.一个有限序列&#xff0c;可以为空 B. 一个有限序列&#xff0c;不可以为空 C. 一个无限序列&#xff0c;可以为空…

(SH) HS-PEG-Cy5.5/CY7/CY5 巯基聚乙二醇Cy5.5/Cy7/Cy5

(SH) HS-PEG-Cy5.5/CY7/CY5 巯基聚乙二醇Cy5.5/Cy7/Cy5 【中文名称】花菁染料Cy5.5-聚乙二醇-巯醇 【英文名称】Cy5.5-PEG-SH 【结 构 】 【品 牌】碳水科技&#xff08;Tanshtech&#xff09; 【纯 度】95%以上 【保 存】-20℃ 【规 格】5mg&#xff0c;10m…

替换windows11 c:/windows/system32/下的dll

找到注册表中的这一项 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\icssvc\Settings 添加 WifiMaxPeers dword 值 32位 最大值是128 设置完成后重启icssvc服务 sc stop icssvc sc start icssvc 由于win11不小心装了preview版本&#xff0c;貌似这个8个最大的已经限定…

冯唐成事心法笔记 —— 知智慧

系列文章目录 冯唐成事心法笔记 —— 知己 冯唐成事心法笔记 —— 知人 冯唐成事心法笔记 —— 知世 冯唐成事心法笔记 —— 知智慧 文章目录 系列文章目录PART 4 知智慧 知可为&#xff0c;知不可为大势不可为怎么办为什么人是第一位的多谈问题&#xff0c;少谈道理用金字塔…

公园设施3D可视化:游园新体验,触手可及的未来

在数字化浪潮席卷全球的今天&#xff0c;我们的生活正在经历一场前所未有的变革。从智能家居到无人驾驶&#xff0c;从在线购物到虚拟现实&#xff0c;科技的力量正在不断刷新我们对世界的认知。而今&#xff0c;这一变革的触角已经延伸到了我们休闲娱乐的场所——公园。 想象一…

用6000万养废3个孩子,“精英教育”的遮羞布终于被掀开了

这几天刷到这样一条笔记。 主人公是一位60岁的香港驻上海的外资行高管&#xff0c;为了培养3个孩子&#xff0c;在他们身上花了6000万&#xff0c;但如今却没有一个孩子获得“成功”。 6000万的投入&#xff0c;换来3个孩子的一事无成&#xff0c;这样的教育算是失败吗&#x…

【Linux】信号的产生

目录 一. 信号的概念signal() 函数 二. 信号的产生1. 键盘发送2. 系统调用kill()raise()abort() 3. 软件条件alarm() 4. 硬件异常除零错误:野指针: 三. 核心转储 一. 信号的概念 信号是消息的载体, 标志着不同的行为; 是进程间发送异步信息的一种方式, 属于软中断. 信号随时都…

麒麟 Kylin V10 一键安装 Oracle 11GR2 单机 ASM(231017)

前言 Oracle 一键安装脚本&#xff0c;演示麒麟 Kylin V10 一键安装 Oracle 11GR2 单机 ASM&#xff08;231017&#xff09;过程&#xff08;全程无需人工干预&#xff09;&#xff1a;&#xff08;脚本包括 ORALCE PSU/OJVM 等补丁自动安装&#xff09; ⭐️ 脚本下载地址&a…

mp4转mpg怎么转?3个好用软件推荐~

mpg文件格式&#xff0c;即MPEG&#xff08;Moving Picture Experts Group&#xff09;格式&#xff0c;起源于1993年&#xff0c;由国际标准化组织&#xff08;ISO&#xff09;制定。当时视频传输的需求催生了这一高效的视频压缩标准&#xff0c;其设计目的在于在保持相对较好…

数据科学与大数据(学习记录)

这个专业或者方向&#xff0c;这个行业有一句话叫做工具决定下限&#xff0c;分析决定上限。通过数据解决问题的思路是最重要的&#xff0c;对于这类型人才.数据具有四大特性&#xff0c;一个是可以反复使用&#xff0c;一个是客观,量化,机器可处理.常见的分析流程&#xff0c;…

广州大学计算机网络实验报告五《网络程序设计》2023年

广州大学学生实验报告 开课学院及实验室&#xff1a; 学院 年级、专业、班 姓名 学号 实验课程名称 计算机网络实验 成绩 实验项目名称 网络程序设计 指导老师 &#xff08;1&#xff09;实验目的 通过程序模拟网桥的工作原理以及检验和的计算&am…