查看: 34|回复: 0

动态规划实战:牛客3895题最大子矩阵和问题详解

[复制链接]
  • TA的每日心情

    昨天 16:28
  • 签到天数: 19 天

    [LV.4]偶尔看看III

    17

    主题

    0

    回帖

    49

    积分

    新手上路

    Rank: 1

    积分
    49
    发表于 2025-6-28 13:48:22 | 显示全部楼层 |阅读模式
    一、问题背景与算法思路
    本题需要在一个n×n的矩阵中找出和最大的子矩阵。我们采用经典的"降维打击"策略,将二维矩阵问题转化为一维数组的最大子段和问题,通过动态规划高效求解。
    二、完整代码实现(带详细注释)
    1. #include <iostream>
    2. #include <vector>
    3. #include <climits>
    4. using namespACe std;

    5. // 求解一维数组的最大子段和(Kadane算法)
    6. int maxSubArray(vector<int>& nums) {
    7.     int maxSum = nums[0];  // 全局最大值
    8.     int current = nums[0]; // 当前连续子数组和
    9.    
    10.     for(int i = 1; i < nums.size(); i++) {
    11.         // 决策:是单独取当前元素,还是接续前面的子数组
    12.         current = max(nums[i], current + nums[i]);
    13.         // 更新全局最大值
    14.         maxSum = max(maxSum, current);
    15.     }
    16.     return maxSum;
    17. }

    18. // 求解二维矩阵的最大子矩阵和
    19. int maxSubMatrix(vector<vector<int>>& matrix) {
    20.     int n = matrix.size();
    21.     int maxSum = INT_MIN; // 初始化为最小整数值
    22.    
    23.     // 枚举所有可能的行范围(从上边界top到下边界bottom)
    24.     for(int top = 0; top < n; top++) {
    25.         vector<int> temp(n, 0); // 存储列累加结果
    26.         
    27.         for(int bottom = top; bottom < n; bottom++) {
    28.             // 将当前行范围内的列累加
    29.             for(int col = 0; col < n; col++) {
    30.                 temp[col] += matrix[bottom][col];
    31.             }
    32.             // 对列累加结果求最大子段和
    33.             int current = maxSubArray(temp);
    34.             // 更新全局最大值
    35.             maxSum = max(maxSum, current);
    36.         }
    37.     }
    38.     return maxSum;
    39. }

    40. int main() {
    41.     int n;
    42.     cin >> n;
    43.     vector<vector<int>> matrix(n, vector<int>(n));
    44.    
    45.     // 读取n×n矩阵
    46.     for(int i = 0; i < n; i++) {
    47.         for(int j = 0; j < n; j++) {
    48.             cin >> matrix[i][j];
    49.         }
    50.     }
    51.    
    52.     // 输出最大子矩阵和
    53.     cout << maxSubMatrix(matrix) << endl;
    54.     return 0;
    55. }
    复制代码
    三、关键算法要点
    • 降维思想:通过列累加将二维问题转化为一维
    • Kadane算法:O(n)时间求最大子段和
    • 边界处理:正确初始化最大值(INT_MIN)
    • 累加技巧:逐步累加行减少重复计算

    四、复杂度分析
    • 时间复杂度:O(n³) (枚举行O(n²) × Kadane算法O(n))
    • 空间复杂度:O(n) (临时数组存储列累加和)

    五、常见错误提醒
    • 忘记初始化maxSum为INT_MIN
    • 列累加时索引错误
    • 边界条件处理不当(如n=1时)
    • 数据类型范围不够导致溢出

    六、学习价值
    通过本题可以掌握:
    • 二维问题的降维处理技巧
    • 动态规划的状态转移思想
    • Kadane算法的精妙设计
    • 矩阵问题的常见处理模式

    来源:动态规划实战:牛客3895题最大子矩阵和问题详解

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    快速回复 返回顶部 返回列表