【2025华为OD机考真题】- 光伏场地建设规划(B卷-100分)(C++版)

🔔本文收录于「最新最全华为OD机试真题(C++版)」专栏,手把手带你零基础教学华为OD机试。本题集提供最优题解思路,解题步骤,代码解析,复杂度分析及最优题解源码等,支持多语言题解,助你轻松拿捏OD机考,一举上岸!安利大家关注&&收藏&&订阅题库正在疯狂收录中,up!up!up!!
🚫提醒:拒绝一切代考/替考,违法必究!专栏所写题库均搜集于互联网,经过精心筛选和整理,结合数位十多年大厂实战经验资深大佬经验所撰,欢迎订阅。
  
💗订阅福利:一次订阅,可永久免费阅读,提供在线答疑解惑,后续题库更新皆可阅读使用!

🔥所有题目均有六种语言实现,汇总如下🔥

如上题库均已同步更新至最新华为OD机试真题,赶紧操练起来吧~~

📚1. 题目描述

📢 具体题目描述如下:

祖国西北部有一片大片荒地,其中零星的分布着一些湖泊,保护区,矿区;整体上常年光照良好,但是也有一些地区光照不太好。某电力公司希望在这里建设多个光伏电站,生产清洁能源。对每平方公里的土地进行了发电评估,其中不能建设的区域发电量为 0kw,可以发电的区域根据光照,地形等给出了每平方公里年发电量 x 千瓦。我们希望能够找到其中集中的矩形区域建设电站,能够获得良好的收益。

📝2. 输入描述

第一行输入为调研的地区长,宽,以及准备建设的电站【长宽相等,为正方形】的边长,最低要求的发电量之后每行为调研区域每平方公里的发电量。

例如,输入为:

2 5 2 6
1 3 4 5 8
2 3 6 7 1

表示调研的区域大小为长2宽5的矩形,我们要建设的电站的边长为2,建设电站最低发电量为6。

🖥️3. 输出描述

输出为这样的区域有多少个
上述输入长宽为2的正方形满足发电量大于等于6的区域有4个。

则输出为: 4

备注: 其中 被调研的区域的长宽均大于等于 1,建设电站的边长大于等于 1,任何区域的发电量大于等于 0

🔍4. 示例演示

✨4.1 示例1

输入:

2 5 2 6
1 3 4 5 8
2 3 6 7 1

输出:

4

示例说明:

  • 需要构建大小为2的子矩阵,且这些子矩阵的发电量总和需要大于等于6。
  • 可能的子矩阵和分别为:
    • 子矩阵((0,0)到(1,1)):1+3+2+3 = 9
    • 子矩阵((0,1)到(1,2)):3+4+3+6 = 16
    • 子矩阵((0,2)到(1,3)):4+5+6+7 = 22
    • 子矩阵((0,3)到(1,4)):5+8+7+1 = 21
  • 所以总共有4个子矩阵满足发电量大于等于6。

✨4.2 示例2

输入:

2 5 1 6
1 3 4 5 8
2 3 6 7 1

输出:

3

示例说明: 输入长为2,宽为5的场地,建设的场地为正方形场地,边长为1,要求场地的发电量大于等于6

✨4.3 示例3

输入:

2 5 1 0
1 3 4 5 8
2 3 6 7 1

输出:

10

示例说明: 输入长为 2,宽为5的场地,建设的场地为正方形场地,边长为1,要求场地的发电量大于等于0即可

温馨提醒: 大家在参加华为OD机试时,切记不要仅仅死记硬背题解代码。真正的通过率取决于你对代码的理解能力。建议你在理解基本原理和逻辑的基础上,模仿并自己编写代码,这样才能更有效地应对机试。

🔑5. 解题分析

🤔5.1 问题理解

这道题的目的是在一个给定的矩阵中,寻找所有大小为 width x width 的子矩阵,计算这些子矩阵的发电量总和,并统计发电量大于等于给定阈值 pow 的子矩阵个数。问题给定了一个矩阵,矩阵中每个位置表示一个区域的发电量,且要求找到符合条件的矩形区域数目。

输入包括:

  • 矩阵的行数和列数 rowcol
  • 电站的边长 width
  • 最低发电量阈值 pow
  • 矩阵的每个元素表示该区域的年发电量。

输出要求:

  • 计算并输出满足发电量大于等于 pow 的子矩阵的数量。

💡5.2 解题思路

  1. 前缀和计算

    • 通过前缀和(prefix sum)技术,能够高效地计算任意子矩阵的和。前缀和矩阵 prefixSum 的每个元素 prefixSum[i][j] 表示从 (0,0) 到 (i-1,j-1) 的子矩阵和。通过前缀和公式,任意子矩阵的和可以快速计算。
  2. 滑动窗口

    • 对于每一个可能的子矩阵,遍历其左上角的位置,使用前缀和计算该子矩阵的发电量和。具体地,遍历所有可能的 (i, j) 作为子矩阵左上角的位置,计算这个 width x width 的子矩阵的和,并与给定的发电量阈值 pow 进行比较。
  3. 条件判断

    • 如果该子矩阵的总和大于等于 pow,则满足条件,计数加一。
  4. 效率

    • 通过前缀和的计算,避免了重复计算子矩阵的和,使得问题的时间复杂度降低。每次计算子矩阵和的操作可以在常数时间内完成。

🎯5.3 问题考点

  1. 前缀和:通过前缀和优化矩阵区域求和的计算。
  2. 子矩阵和计算:通过滑动窗口方法遍历所有可能的子矩阵,且使用前缀和快速求得每个子矩阵的总和。
  3. 二维数组处理:处理矩阵和子矩阵的遍历。
  4. 复杂度优化:通过前缀和方法减少不必要的重复计算,显著优化时间复杂度。

📝5.4 解题步骤

  1. 输入解析:首先读取矩阵的行数、列数、边长 width 和最低要求的发电量 pow,然后读取矩阵的每个元素,构建二维矩阵 region

  2. 计算前缀和

    • 初始化一个大小为 (row+1) x (col+1) 的前缀和矩阵 prefixSum,其中每个元素 prefixSum[i][j] 表示从 (0,0) 到 (i-1,j-1) 的子矩阵和。
    • 填充前缀和矩阵,通过公式 prefixSum[i][j] = prefixSum[i-1][j] + prefixSum[i][j-1] - prefixSum[i-1][j-1] + region[i-1][j-1] 计算每个位置的值。
  3. 遍历子矩阵

    • 遍历所有可能的 (i, j) 作为子矩阵的左上角位置,计算其对应的发电量和。对于每个位置,使用前缀和公式计算大小为 width x width 的子矩阵的和。
  4. 比较和计数

    • 对每个子矩阵的和,如果其大于或等于给定的发电量阈值 pow,则增加计数。
  5. 输出结果:输出满足条件的子矩阵数量。

通过以上步骤,可以高效地完成这道题,并得出结果。

💻6. 解题Coding

  根据如上题解思路,进行代码实战,大家请看如下,建议不要死记硬背代码,要理解其题型及实现思路,别担心,代码我都会给出超详细注释,你一定能看明白的。

✅6.1 代码实现(C++版)

#include <iostream>
#include <vector>

using namespace std;

// 计算二维矩阵的前缀和
vector<vector<int>> calculatePrefixSum(const vector<vector<int>>& matrix, int row, int col) {
    vector<vector<int>> prefixSum(row + 1, vector<int>(col + 1, 0));

    // 填充前缀和矩阵
    for (int i = 1; i <= row; i++) {
        for (int j = 1; j <= col; j++) {
            prefixSum[i][j] = prefixSum[i - 1][j] + prefixSum[i][j - 1]
                              - prefixSum[i - 1][j - 1] + matrix[i - 1][j - 1];
        }
    }

    return prefixSum;
}

// 计算指定子矩阵的和
int calculateSubMatrixSum(const vector<vector<int>>& prefixSum, int row, int col, int width) {
    // 确定子矩阵的四个角
    int rowStart = row;
    int rowEnd = row + width - 1;
    int colStart = col;
    int colEnd = col + width - 1;

    // 使用前缀和公式计算子矩阵的和
    return prefixSum[rowEnd + 1][colEnd + 1] - prefixSum[rowEnd + 1][colStart]
           - prefixSum[rowStart][colEnd + 1] + prefixSum[rowStart][colStart];
}

int main() {
    int row, col, width, pow;
    cin >> row >> col >> width >> pow;

    vector<vector<int>> region(row, vector<int>(col));

    // 输入矩阵数据
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < col; j++) {
            cin >> region[i][j];
        }
    }

    // 计算前缀和
    vector<vector<int>> prefixSum = calculatePrefixSum(region, row, col);

    int res = 0;

    // 遍历所有可能的子矩阵,计算其和并进行比较
    for (int i = 0; i < row - width + 1; i++) {
        for (int j = 0; j < col - width + 1; j++) {
            int count = calculateSubMatrixSum(prefixSum, i, j, width);
            if (count >= pow) {
                res++;  // 如果子矩阵的和大于或等于目标值,则计数
            }
        }
    }

    // 输出结果
    cout << res << endl;

    return 0;
}

⏱6.2 时间&空间复杂度

时间复杂度

  • 前缀和计算calculatePrefixSum 函数的时间复杂度是 O(row * col),因为我们需要遍历整个矩阵并根据动态规划公式计算每个前缀和。
  • 子矩阵计算:在主函数中,我们遍历所有可能的子矩阵,计算每个子矩阵的和。每个子矩阵和的计算是 O(1) 的(通过前缀和快速计算),而遍历所有可能的子矩阵的次数是 (row - width + 1) * (col - width + 1),即大约是 O(row * col),因此该部分的时间复杂度是 O(row * col)。

因此,整体时间复杂度是 O(row * col),这是最主要的时间复杂度。

空间复杂度

  • region 矩阵占用 O(row * col) 空间。
  • prefixSum 矩阵也占用 O(row * col) 空间。

因此,空间复杂度为 O(row * col)。

⛓‍💥6.3 代码解析

  1. calculatePrefixSum 函数
    • 该函数用来计算给定矩阵的前缀和。前缀和矩阵 prefixSum[i][j] 表示从矩阵 (0,0) 到 (i-1,j-1) 的所有元素之和。前缀和的计算公式是:

p r e f i x S u m [ i ] [ j ] = p r e f i x S u m [ i − 1 ] [ j ] + p r e f i x S u m [ i ] [ j − 1 ] − p r e f i x S u m [ i − 1 ] [ j − 1 ] + m a t r i x [ i − 1 ] [ j − 1 ] prefixSum[i][j] = prefixSum[i-1][j] + prefixSum[i][j-1] - prefixSum[i-1][j-1] + matrix[i-1][j-1] prefixSum[i][j]=prefixSum[i1][j]+prefixSum[i][j1]prefixSum[i1][j1]+matrix[i1][j1]

  • 通过这种方式,我们可以在 O(1) 时间内计算任意子矩阵的和,从而大大提高了效率。
  1. calculateSubMatrixSum 函数

    • 该函数根据前缀和矩阵计算指定子矩阵的和。子矩阵的和可以通过以下公式快速计算:
      t e x t S u m = p r e f i x S u m [ r o w E n d + 1 ] [ c o l E n d + 1 ] − p r e f i x S u m [ r o w E n d + 1 ] [ c o l S t a r t ] − p r e f i x S u m [ r o w S t a r t ] [ c o l E n d + 1 ] + p r e f i x S u m [ r o w S t a r t ] [ c o l S t a r t ] text{Sum} = prefixSum[rowEnd+1][colEnd+1] - prefixSum[rowEnd+1][colStart] - prefixSum[rowStart][colEnd+1] + prefixSum[rowStart][colStart] textSum=prefixSum[rowEnd+1][colEnd+1]prefixSum[rowEnd+1][colStart]prefixSum[rowStart][colEnd+1]+prefixSum[rowStart][colStart]

    • 这样可以在 O(1) 时间内计算出子矩阵的和。

  2. 主函数

    • main 函数中,首先读取输入矩阵并计算前缀和。
    • 然后遍历所有可能的子矩阵,计算其和并与目标值进行比较,如果大于或等于目标值,则计数。

📝6.4 小结

该程序通过前缀和算法高效地计算了矩阵的子矩阵和。通过先计算前缀和矩阵,后续的子矩阵和可以在 O(1) 时间内获得,使得求解效率大大提高。时间复杂度为 O(row * col),空间复杂度也是 O(row * col),适合处理大规模的矩阵问题。

📥7. 附录源码(Java版)

  针对如上分享OD机试真题之外,这里我还开源全部OD机试原真题源码,供同学们一对一学习!对照每题都有题目号及详细代码注释。Gitee,例如题序号为1,则题解代码对应文件夹OD1,题序号为5,则题解代码对应文件夹OD5,以此类推,目的就是为了方便大家学习,一举上岸!(这里的题序号指专栏导航贴中表格一列的序号)

🧧福利赠与你🧧

  如果你还想学习更多相关OD真题题解,都建议直接毫不犹豫地学习此专栏「最新最全真题华为OD机试真题(全栈版)」,快速掌握Java、Python、C++、JavaScript、Go等多种热门语言详细解题,快速突破华为OD机试,实现350+高分目标。还将提供线上多端答疑交流,解决你的所有问题!

🎁安利其他语言版本题解册🎁

注意: 上述任意专栏一次订阅,获永久免费阅读权限,后续更新都能学习。
声明: 拒绝一切形式的代考,替考行为,务必诚信考试!!!本人所写题库均搜集于互联网。

👩‍💻Who am I?

我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云多年度十佳博主&最具价值贡献奖,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;更多精彩福利点击这里;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。

-End-

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bug菌¹

你的鼓励将是我创作的最大动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值