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):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }