URAL 1146 Maximum Sum(DP)

Given a 2-dimensional array of positive and negative integers, find the sub-rectangle with the largest sum. The sum of a rectangle is the sum of all the elements in that rectangle. In this problem the sub-rectangle with the largest sum is referred to as the  maximal sub-rectangle. A sub-rectangle is any contiguous sub-array of size 1 × 1 or greater located within the whole array.
As an example, the maximal sub-rectangle of the array:
0 −2 −7 0
9 2 −6 2
−4 1 −4 1
−1 8 0 −2
is in the lower-left-hand corner and has the sum of 15.

Input

The input consists of an  N ×  N array of integers. The input begins with a single positive integer  Non a line by itself indicating the size of the square two dimensional array. This is followed by  N  2integers separated by white-space (newlines and spaces). These  N  2 integers make up the array in row-major order (i.e., all numbers on the first row, left-to-right, then all numbers on the second row, left-to-right, etc.).  N may be as large as 100. The numbers in the array will be in the range [−127, 127].

Output

The output is the sum of the maximal sub-rectangle.
 
题目大意:给一个n*n的矩阵,求和最大的子矩阵。
思路:用sum[i][j]表示从mat[1][j]~mat[i][j]的总和(从1开始计数)
然后枚举上下两行夹着的矩阵,设第一行为r1,第二行为r2,复杂度为O(n^2),然后计算这两行夹着的最大子矩阵。
用sum[r2][j] - sum[r1 - 1][j]表示mat[r1][j]~mat[r2][j]的总和。
那么,我们把r1~r2之间的列,每一列算出来,就变成了一个只有n个元素的一维数组,求最大连续子序列。
这个就是经典问题了,设a[i] = sum[r2][i] - sum[r1][i],初始化t = 0。
t从a[1]加到a[n],当t < 0的时候,令t = 0,算到 i 的时候,t就表示以a[i - 1]为结尾的最大后缀。
因为,如果我们算到a[i],此时t < 0,那么,算a[i + 1]的时候,肯定不会加上a[i]和前面的数字,不管怎么加,前面的数都小于0,还是不加的好。
能加的肯定要加上,所以复杂度为O(n)。
总复杂度为O(n^3)
 
代码(0.031S):
 1 #include <cstdio>

 2 #include <iostream>

 3 #include <algorithm>

 4 #include <cstring>

 5 using namespace std;

 6 

 7 const int MAXN = 110;

 8 

 9 int mat[MAXN][MAXN], n;

10 int sum[MAXN][MAXN];

11 

12 void calsum() {

13     for(int i = 1; i <= n; ++i)

14         for(int j = 1; j <= n; ++j) sum[i][j] = sum[i - 1][j] + mat[i][j];

15 }

16 

17 int solve() {

18     int ans = -999;

19     for(int r1 = 1; r1 <= n; ++r1) {

20         for(int r2 = r1; r2 <= n; ++r2) {

21             int t = 0;

22             for(int j = 1; j <= n; ++j) {

23                 t += sum[r2][j] - sum[r1 - 1][j];

24                 ans = max(t, ans);

25                 if(t < 0) t = 0;

26             }

27         }

28     }

29     return ans;

30 }

31 

32 int main() {

33     scanf("%d", &n);

34     for(int i = 1; i <= n; ++i)

35         for(int j = 1; j <= n; ++j) scanf("%d", &mat[i][j]);

36     calsum();

37     printf("%d\n", solve());

38 }
View Code

 

你可能感兴趣的:(max)