
🔔本文收录于「最新最全华为OD机试真题(C++版)」专栏,手把手带你零基础教学华为OD机试。本题集提供最优题解思路,解题步骤,代码解析,复杂度分析及最优题解源码等,支持多语言题解,助你轻松拿捏OD机考,一举上岸!安利大家关注&&收藏&&订阅!题库正在疯狂收录中,up!up!up!!
🚫提醒:拒绝一切代考/替考,违法必究!专栏所写题库均搜集于互联网,经过精心筛选和整理,结合数位十多年大厂实战经验资深大佬经验所撰,欢迎订阅。
💗订阅福利:一次订阅,可永久免费阅读,提供在线答疑解惑,后续题库更新皆可阅读使用!
🔥所有题目均有六种语言实现,汇总如下🔥
- 【华为OD机试】最新最全真题汇总A+B+C+D+E卷【全栈版】
- 【华为OD机试】最新最全真题汇总A+B+C+D+E卷【Java版】
- 【华为OD机试】最新最全真题汇总A+B+C+D+E卷【Python版】
- 【华为OD机试】最新最全真题汇总A+B+C+D+E卷【C版】
- 【华为OD机试】最新最全真题汇总A+B+C+D+E卷【C++版】
- 【华为OD机试】最新最全真题汇总A+B+C+D+E卷【Golang版】
- 【华为OD机试】最新最全真题汇总A+B+C+D+E卷【JavaScript版】
如上题库均已同步更新至最新华为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
的子矩阵个数。问题给定了一个矩阵,矩阵中每个位置表示一个区域的发电量,且要求找到符合条件的矩形区域数目。
输入包括:
- 矩阵的行数和列数
row
和col
。 - 电站的边长
width
。 - 最低发电量阈值
pow
。 - 矩阵的每个元素表示该区域的年发电量。
输出要求:
- 计算并输出满足发电量大于等于
pow
的子矩阵的数量。
💡5.2 解题思路
-
前缀和计算:
- 通过前缀和(prefix sum)技术,能够高效地计算任意子矩阵的和。前缀和矩阵
prefixSum
的每个元素prefixSum[i][j]
表示从 (0,0) 到 (i-1,j-1) 的子矩阵和。通过前缀和公式,任意子矩阵的和可以快速计算。
- 通过前缀和(prefix sum)技术,能够高效地计算任意子矩阵的和。前缀和矩阵
-
滑动窗口:
- 对于每一个可能的子矩阵,遍历其左上角的位置,使用前缀和计算该子矩阵的发电量和。具体地,遍历所有可能的
(i, j)
作为子矩阵左上角的位置,计算这个width x width
的子矩阵的和,并与给定的发电量阈值pow
进行比较。
- 对于每一个可能的子矩阵,遍历其左上角的位置,使用前缀和计算该子矩阵的发电量和。具体地,遍历所有可能的
-
条件判断:
- 如果该子矩阵的总和大于等于
pow
,则满足条件,计数加一。
- 如果该子矩阵的总和大于等于
-
效率:
- 通过前缀和的计算,避免了重复计算子矩阵的和,使得问题的时间复杂度降低。每次计算子矩阵和的操作可以在常数时间内完成。
🎯5.3 问题考点
- 前缀和:通过前缀和优化矩阵区域求和的计算。
- 子矩阵和计算:通过滑动窗口方法遍历所有可能的子矩阵,且使用前缀和快速求得每个子矩阵的总和。
- 二维数组处理:处理矩阵和子矩阵的遍历。
- 复杂度优化:通过前缀和方法减少不必要的重复计算,显著优化时间复杂度。
📝5.4 解题步骤
-
输入解析:首先读取矩阵的行数、列数、边长
width
和最低要求的发电量pow
,然后读取矩阵的每个元素,构建二维矩阵region
。 -
计算前缀和:
- 初始化一个大小为
(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]
计算每个位置的值。
- 初始化一个大小为
-
遍历子矩阵:
- 遍历所有可能的
(i, j)
作为子矩阵的左上角位置,计算其对应的发电量和。对于每个位置,使用前缀和公式计算大小为width x width
的子矩阵的和。
- 遍历所有可能的
-
比较和计数:
- 对每个子矩阵的和,如果其大于或等于给定的发电量阈值
pow
,则增加计数。
- 对每个子矩阵的和,如果其大于或等于给定的发电量阈值
-
输出结果:输出满足条件的子矩阵数量。
通过以上步骤,可以高效地完成这道题,并得出结果。
💻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 代码解析
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[i−1][j]+prefixSum[i][j−1]−prefixSum[i−1][j−1]+matrix[i−1][j−1]
- 通过这种方式,我们可以在 O(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) 时间内计算出子矩阵的和。
-
-
主函数:
- 在
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+高分目标。还将提供线上多端答疑交流,解决你的所有问题!
🎁安利其他语言版本题解册🎁
- 【华为OD机试】最新最全真题汇总A+B+C+D+E卷【全栈版】
- 【华为OD机试】最新最全真题汇总A+B+C+D+E卷【Java版】
- 【华为OD机试】最新最全真题汇总A+B+C+D+E卷【Python版】
- 【华为OD机试】最新最全真题汇总A+B+C+D+E卷【C版】
- 【华为OD机试】最新最全真题汇总A+B+C+D+E卷【C++版】
- 【华为OD机试】最新最全真题汇总A+B+C+D+E卷【Golang版】
- 【华为OD机试】最新最全真题汇总A+B+C+D+E卷【JavaScript版】
注意: 上述任意专栏一次订阅,获永久免费阅读权限,后续更新都能学习。
声明: 拒绝一切形式的代考,替考行为,务必诚信考试!!!本人所写题库均搜集于互联网。
👩💻Who am I?
我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云多年度十佳博主&最具价值贡献奖,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;更多精彩福利点击这里;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。

-End-