思路
记录这道题主要是为了记录二位前缀和的做题思路,毕竟CSP都遇见现题了,当时还只过了8个点...
其实前缀和也是一种形式的dp,这里借用LeetCode-304官方题解的图片,它画得很清晰了
[图片缺失] 原图:https://www.edisoncgh.com/wp-content/uploads/2021/04/1614650837-SAIiWg-1-1024x576.png
我们设dp[i][j]表示从矩阵左上角(0,0)到当前位置(i,j)的所有值之和,则不难得出图中的转移方程。减去dp[i-1][j-1]的原因是它在计算dp[i][j-1]+dp[i-1][j]中被计算了两次,要减掉多余的那一次。
这种思路在LeetCode周赛#225的T3中也有体现。
当我们对所有的(i,j)都算出前缀和后,用四重循环去依次枚举每一对左上角与右下角就行了。虽然纸面复杂度有O(n²* m²),但每一个右下角一定在左下角后面,所以对右下角的枚举并没有严格的平方级复杂度,所以还是能把题混过去的。
代码
int sum[110][110];
class Solution {
public:
int maxSumSubmatrix(vector<vector<int>>& mat, int k) {
int m = mat.size(), n = mat[0].size();
for(int i = 1; i <= m; i++){
for(int j = 1; j <= n; j++){
sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + mat[i - 1][j - 1];
}
}
int ans = INT_MIN;
for(int i = 1; i <= m; i++){
for(int j = 1; j <= n; j++){
for(int p = i; p <= m; p++){
for(int q = j; q <= n; q++){
int cur = sum[p][q] - sum[i - 1][q] - sum[p][j - 1] + sum[i - 1][j - 1];
if(cur <= k){
ans = max(ans,cur);
}
}
}
}
}
return ans;
}
};