题目链接:
POJ:http://poj.org/problem?id=1050
HDU:http://acm.hdu.edu.cn/showproblem.php?pid=1081
题意:给出一个n*n的矩阵,正负均有。求一个子矩阵使得该子矩阵的和尽可能的大。
思路:类似于最大子段和,即将前i行至前j行的矩阵压缩成一行,利用一个数组c,c[k]表示第k列从第i行到第j行的和,接下来只需对数组c求最大子段和,结果即为第i行到第j行中的最大子矩阵和。
代码:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
const int N = 5e2 + 10;
const int INF = 0x3f3f3f3f;
long long a[N][N];
long long c[N];
int n, m;
long long getAns() {
long long ans = 0;
for (int i = 1; i <= n; i++) {
for (int j = i; j <= n; j++) {
long long res = 0;
for (int k = 1; k <= m; k++) {
c[k] = (i == j ? a[i][k] : c[k] + a[j][k]);
if (res < 0)
res = c[k];
else
res = res + c[k];
ans = max(res, ans);
}
}
}
return ans;
}
int main() {
while (scanf("%d%d", &m, &n) != EOF) {
long long _max = -INF;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
scanf("%lld", &a[i][j]);
_max = max(_max, a[i][j]);
}
}
// 若矩阵全为负数,则认为结果为0
long long ans = (_max < 0LL ? 0 : getAns());
printf("%lld\n", ans);
}
return 0;
}