线性动态规划:最大子矩阵和问题(进阶版——带限制条件的最大子矩阵和,限制子矩阵面积至少为S)
字数 1635 2025-12-01 22:23:20
线性动态规划:最大子矩阵和问题(进阶版——带限制条件的最大子矩阵和,限制子矩阵面积至少为S)
题目描述
给定一个m x n的整数矩阵,要求找到一个子矩阵(连续的行和列组成),使得该子矩阵内所有元素的和最大,并且子矩阵的面积(即行数乘以列数)至少为S。如果存在多个这样的子矩阵,返回最大的和。注意,子矩阵不能为空。
解题过程
-
问题分析
最大子矩阵和问题通常通过压缩矩阵为一维问题来解决(即枚举所有可能的行区间,将多行合并为一行,然后在该行上求解最大子数组和)。但本题增加了面积至少为S的限制,直接应用传统方法无法处理,因为最大子数组和不一定满足面积要求。 -
关键思路
- 枚举所有可能的行区间(上边界i和下边界j),将矩阵第i行到第j行之间的每一列求和,压缩成一个一维数组
colSum(长度为n)。 - 在
colSum数组上,问题转化为:找到一个连续子数组,其和最大,且子数组长度(即列数)至少为minCols,其中minCols = ceil(S / (j-i+1))(因为行数固定时,列数需满足面积≥S)。 - 对每个行区间,计算满足列数限制的最大子数组和,更新全局最大值。
- 枚举所有可能的行区间(上边界i和下边界j),将矩阵第i行到第j行之间的每一列求和,压缩成一个一维数组
-
动态规划状态定义
对于压缩后的一维数组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]。
- 如果子数组长度正好为L,和为
- 综合得到:
dp[k] = max(prefixSum[k+1] - prefixSum[k-L+1], dp[k-1] + 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数组。
示例
假设矩阵为:
[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。