题目链接:
PREV-26 最大子阵
思路:
首先我们需要学会求一维最大子序列和(这里就不多赘述啦)
此题我们枚举这个子矩阵的上底和下底即原矩阵的两行,对于原矩阵的每一列我们都用前缀和数组记录下来;
假设现在枚举第r
和第rr
行,我们设立数组v
(下标从1
到m
),v[i]
的值即为原矩阵a[r][i] + a[r + 1][i] + ... + a[rr][i]
,此时我们只需求一维数组v
的最大子序列和即可;
时间复杂度
,但是常数不大,可以AC
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 505;
int n, m, a[505][505], sum[505][505];
int main() {
#ifdef MyTest
freopen("Sakura.txt", "r", stdin);
#endif
scanf("%d %d", &n, &m);
int ans = -5005;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
{ scanf("%d", &a[i][j]); ans = max(ans, a[i][j]); }
if(ans <= 0) { cout << ans; exit(0); }
for(int j = 1; j <= m; ++j)
for(int i = 1; i <= n; ++i)
sum[i][j] = (i ? sum[i - 1][j] : 0) + a[i][j];
for(int r = 1; r <= n; ++r)
for(int rr = r; rr <= n; ++rr) {
vector<int> v(m + 1);
for(int j = 1; j <= m; ++j) v[j] = sum[rr][j] - sum[r - 1][j];
int rcd = 0;
for(int i = 1; i <= m; i++) {
if(rcd < 0) rcd = 0;
rcd += v[i];
ans = max(ans, rcd);
}
}
cout << ans;
return 0;
}