原题链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1051
思路:定义dp[i][j][l]为以第i行第j列为左下角元素的长度为l最大子矩阵和,于是dp[i][j][l] =max(dp[i-1][j][l] + sum(j,j+l-1));然后预处理后缀和,滚动数组优化一下空间即可
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
const int MAXN = 5e2 + 5;
const int MOD = 1e9 + 7;
typedef long long LL;
const double PI = acos(-1.0);
const double E = exp(1.0);
using namespace std;
LL cs[MAXN][MAXN], dp[2][MAXN][MAXN], a[MAXN][MAXN], n, m;
void preProcess() {
for (int i = 1; i <= m; i++) {
for (int j = n; j >= 1; j--) {
cs[i][j] = cs[i][j + 1] + a[i][j];
}
}
}
LL solve() {
LL ans = 0;
int cur = 0;
for (int i = 1; i <= m; i++) {
cur ^= 1;
for (int j = n; j >= 1; j--) {
for (int l = 1; l + j - 1 <= n; l++) {
if (dp[cur ^ 1][j][l] < 0) {
dp[cur][j][l] = cs[i][j] - cs[i][j + l];
}
else {
dp[cur][j][l] = dp[cur ^ 1][j][l] + cs[i][j] - cs[i][j + l];
}
ans = max(ans, dp[cur][j][l]);
}
}
}
return ans;
}
int main() {
scanf("%lld %lld", &n, &m);
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
scanf("%lld", &a[i][j]);
}
}
preProcess();
printf("%lld\n", solve());
return 0;
}