一维最大字段和的扩展。
要诀是固定列的左右点,比如左边记录为left, 右边记录为right,那么一个循环left从0到COL,行最大值,那么right从left开始循环到COl,就可以考虑到所有列组合了,这个循环是O(n*n),然后求范围列内的行最大子段和,时间是O(n),
这样巧妙地把二维的问题转化为一维了,最终时间复杂度是O(n^3)。
可以参考Geeks上的讲解,不过他的最大子段和代码写的挺挫的,我的代码会简洁很多,而且也考虑到了负值情况了。
Geeks地址:http://www.geeksforgeeks.org/dynamic-programming-set-27-max-sum-rectangle-in-a-2d-matrix/
#include <stdio.h>
#include <string.h>
#include <limits.h>
const int MAX_N = 100;
int N;
int arr[MAX_N][MAX_N];
int temp[MAX_N];
inline int max(int a, int b) { return a > b ? a : b; }
int kadane(int *A, int n)
{
int sum = 0, maxSum = INT_MIN, i;
for (i = 0; i < n; i++)
{
sum += A[i];
maxSum = max(sum, maxSum);
sum = max(sum, 0);
}
return maxSum;
}
int maximalSubRetangle()
{
int maxSum = INT_MIN;
int left, right, i;
for (left = 0; left < N; left++)
{
memset(temp, 0, sizeof(int) * N);
for (right = left; right < N; ++right)
{
for (i = 0; i < N; i++)
{
temp[i] += arr[i][right];
}
maxSum = max(maxSum, kadane(temp, N));
}
}
return maxSum;
}
int main()
{
while (scanf("%d", &N) != EOF)
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
scanf("%d", &arr[i][j]);
}
}
printf("%d\n", maximalSubRetangle());
}
return 0;
}