线性动态规划:最大子矩阵和问题(进阶版——带限制条件的最大子矩阵和,限制子矩阵面积至少为S)
字数 1635 2025-12-01 22:23:20

线性动态规划:最大子矩阵和问题(进阶版——带限制条件的最大子矩阵和,限制子矩阵面积至少为S)

题目描述
给定一个m x n的整数矩阵,要求找到一个子矩阵(连续的行和列组成),使得该子矩阵内所有元素的和最大,并且子矩阵的面积(即行数乘以列数)至少为S。如果存在多个这样的子矩阵,返回最大的和。注意,子矩阵不能为空。

解题过程

  1. 问题分析
    最大子矩阵和问题通常通过压缩矩阵为一维问题来解决(即枚举所有可能的行区间,将多行合并为一行,然后在该行上求解最大子数组和)。但本题增加了面积至少为S的限制,直接应用传统方法无法处理,因为最大子数组和不一定满足面积要求。

  2. 关键思路

    • 枚举所有可能的行区间(上边界i和下边界j),将矩阵第i行到第j行之间的每一列求和,压缩成一个一维数组colSum(长度为n)。
    • colSum数组上,问题转化为:找到一个连续子数组,其和最大,且子数组长度(即列数)至少为minCols,其中minCols = ceil(S / (j-i+1))(因为行数固定时,列数需满足面积≥S)。
    • 对每个行区间,计算满足列数限制的最大子数组和,更新全局最大值。
  3. 动态规划状态定义
    对于压缩后的一维数组A(即colSum),定义状态:

    • dp[k]:以第k个元素结尾的、长度至少为L(minCols)的子数组的最大和。
    • 辅助变量prefixSum:前缀和数组,用于快速计算区间和。
  4. 状态转移方程

    • 计算前缀和prefixSum,使得prefixSum[k] = A[0] + A[1] + ... + A[k-1]
    • 对于以k结尾的子数组:
      • 如果子数组长度正好为L,和为prefixSum[k+1] - prefixSum[k-L+1]
      • 如果长度大于L,则其和可以拆分为:(以k-1结尾的长度≥L的子数组和) + A[k]
    • 综合得到:
      dp[k] = max(prefixSum[k+1] - prefixSum[k-L+1], dp[k-1] + A[k])
      
    • 注意:k需满足k ≥ L-1,否则无法构成长度≥L的子数组。
  5. 算法步骤
    a. 初始化全局最大值globalMax为负无穷。
    b. 枚举所有行区间[i, j](0 ≤ i ≤ j < m):

    • 计算当前行数rows = j-i+1,最小列数minCols = ceil(S / rows)。若minCols > n,跳过该区间。
    • 计算压缩数组colSum:对每列k,colSum[k] = matrix[i][k] + ... + matrix[j][k]
    • colSum计算前缀和prefixSum
    • 初始化dp[minCols-1] = prefixSum[minCols] - prefixSum[0]
    • k = minColsn-1更新dp[k],并更新globalMax
      c. 返回globalMax
  6. 复杂度分析

    • 时间复杂度:O(m² × n),其中枚举行区间为O(m²),每区间内处理为O(n)。
    • 空间复杂度:O(n),用于存储colSumprefixSumdp数组。

示例
假设矩阵为:

[1, 2, -1]
[-3, 1, 4]
[2, -2, 0]

S = 4(面积至少为4)。
当行区间[0,1]时,行数=2,minCols = ceil(4/2)=2,压缩数组为[1+(-3), 2+1, -1+4] = [-2, 3, 3]
前缀和prefixSum = [0, -2, 1, 4]

  • k=1(第2列):dp[1] = prefixSum[2] - prefixSum[0] = 1 - 0 = 1(长度2的子数组[-2,3]和为1)。
  • k=2:dp[2] = max(prefixSum[3]-prefixSum[1], dp[1]+A[2]) = max(4-(-2)=6, 1+3=4) = 6(对应子矩阵为第0-1行、第1-2列,和=3+3=6,面积=2×2=4≥S)。
    最终全局最大值为6。
线性动态规划:最大子矩阵和问题(进阶版——带限制条件的最大子矩阵和,限制子矩阵面积至少为S) 题目描述 给定一个m x n的整数矩阵,要求找到一个子矩阵(连续的行和列组成),使得该子矩阵内所有元素的和最大,并且子矩阵的面积(即行数乘以列数)至少为S。如果存在多个这样的子矩阵,返回最大的和。注意,子矩阵不能为空。 解题过程 问题分析 最大子矩阵和问题通常通过压缩矩阵为一维问题来解决(即枚举所有可能的行区间,将多行合并为一行,然后在该行上求解最大子数组和)。但本题增加了面积至少为S的限制,直接应用传统方法无法处理,因为最大子数组和不一定满足面积要求。 关键思路 枚举所有可能的行区间(上边界i和下边界j),将矩阵第i行到第j行之间的每一列求和,压缩成一个一维数组 colSum (长度为n)。 在 colSum 数组上,问题转化为:找到一个连续子数组,其和最大,且子数组长度(即列数)至少为 minCols ,其中 minCols = ceil(S / (j-i+1)) (因为行数固定时,列数需满足面积≥S)。 对每个行区间,计算满足列数限制的最大子数组和,更新全局最大值。 动态规划状态定义 对于压缩后的一维数组 A (即 colSum ),定义状态: dp[k] :以第k个元素结尾的、长度至少为L( minCols )的子数组的最大和。 辅助变量 prefixSum :前缀和数组,用于快速计算区间和。 状态转移方程 计算前缀和 prefixSum ,使得 prefixSum[k] = A[0] + A[1] + ... + A[k-1] 。 对于以k结尾的子数组: 如果子数组长度正好为L,和为 prefixSum[k+1] - prefixSum[k-L+1] 。 如果长度大于L,则其和可以拆分为: (以k-1结尾的长度≥L的子数组和) + A[k] 。 综合得到: 注意:k需满足 k ≥ L-1 ,否则无法构成长度≥L的子数组。 算法步骤 a. 初始化全局最大值 globalMax 为负无穷。 b. 枚举所有行区间[ i, j](0 ≤ i ≤ j < m): 计算当前行数 rows = j-i+1 ,最小列数 minCols = ceil(S / rows) 。若 minCols > n ,跳过该区间。 计算压缩数组 colSum :对每列k, colSum[k] = matrix[i][k] + ... + matrix[j][k] 。 对 colSum 计算前缀和 prefixSum 。 初始化 dp[minCols-1] = prefixSum[minCols] - prefixSum[0] 。 从 k = minCols 到 n-1 更新 dp[k] ,并更新 globalMax 。 c. 返回 globalMax 。 复杂度分析 时间复杂度:O(m² × n),其中枚举行区间为O(m²),每区间内处理为O(n)。 空间复杂度:O(n),用于存储 colSum 、 prefixSum 和 dp 数组。 示例 假设矩阵为: S = 4(面积至少为4)。 当行区间[ 0,1]时,行数=2, minCols = ceil(4/2)=2 ,压缩数组为 [1+(-3), 2+1, -1+4] = [-2, 3, 3] 。 前缀和 prefixSum = [0, -2, 1, 4] 。 k=1(第2列): dp[1] = prefixSum[2] - prefixSum[0] = 1 - 0 = 1 (长度2的子数组[ -2,3 ]和为1)。 k=2: dp[2] = max(prefixSum[3]-prefixSum[1], dp[1]+A[2]) = max(4-(-2)=6, 1+3=4) = 6 (对应子矩阵为第0-1行、第1-2列,和=3+3=6,面积=2×2=4≥S)。 最终全局最大值为6。