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

 

posted @ 2014-03-06 23:49  Oyking  阅读(343)  评论(0编辑  收藏  举报