1146. Maximum Sum
Time limit: 1.0 second Memory limit: 64 MB
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.
Sample
input | output |
---|---|
4 0 -2 -7 0 9 2 -6 2 -4 1 -4 1 -1 8 0 -2 |
15 |
题意:输入部分第一行是一个正整数N,说明矩阵的大小。下一行后面跟着 个整数。留意这些整数的输入格式可能比较混乱。矩阵是以行优先存储的。N可能和100一样大,矩阵中每个数字的范围为 [-127, 127].
思路1:对矩阵进行穷举。找出所有的子矩阵计算矩阵和并找出最大值。

1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 6 using namespace std; 7 int s[105][105]= {0}; 8 int dp[105][105]= {0}; 9 10 11 12 int main() 13 { 14 // freopen("1.txt","r",stdin); 15 int i,j,ki,kj; 16 int n; 17 while(cin>>n) 18 { 19 for(i=1; i<=n; i++) 20 for(j=1; j<=n; j++) 21 { 22 cin>>s[i][j]; 23 s[i][j]+=s[i-1][j]; 24 s[i-1][j]+=s[i-1][j-1]; 25 }//输入矩阵并且计算从(1,1)到(i-1,j)的矩阵的和值 26 for(i=1; i<=n; i++) 27 s[n][i]+=s[n][i-1];//计算从(1,1)到(n,i)的矩阵的和值 28 int max=-99999999;//特别注意因为 29 for(i=1; i<=n; i++) 30 for(j=1; j<=n; j++) 31 { 32 max=-99999999; 33 for(ki=0; ki<i; ki++) 34 for(kj=0; kj<j; kj++) 35 if(max<s[i][j]-s[i][kj]-s[ki][j]+s[ki][kj])//计算(ki,kj)到(i,j)的子矩阵的和并且和max比较; 36 max=s[i][j]-s[i][kj]-s[ki][j]+s[ki][kj]; 37 dp[i][j]=max; 38 } 39 max=-99999999; 40 for(i=1; i<=n; i++) 41 for(j=1; j<=n; j++) 42 if(max<=dp[i][j]) 43 max=dp[i][j]; 44 cout<<max<<endl; 45 } 46 return 0; 47 }
思路2求最大子矩阵的和,先按列进行枚举起始列和结束列,用数据够快速求出每行起始列到结束列之间各数据的和,然后就可以降成一维的,问题就变成了求最大连续子序列了

1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 5 using namespace std; 6 7 #define N 1100 8 #define INF 0x3f3f3f3f 9 int s[N][N]= {0},dp[N],n; 10 11 void get_sum(int x ,int y) 12 { 13 for(int i=1; i<=n; i++) 14 { 15 dp[i]=s[y][i]-s[x-1][i]; 16 } 17 return ; 18 } 19 20 int DP() 21 { 22 int sum=0,max=-INF; 23 for(int i=1; i<=n; i++) 24 { 25 sum+=dp[i]; 26 max=sum>max?sum:max; 27 if(sum<0) sum=0; 28 } 29 return max; 30 } 31 32 33 34 int main() 35 { 36 int i,j; 37 // freopen("1.txt","r",stdin); 38 while(cin>>n) 39 { 40 for(i=1; i<=n; i++) 41 for(j=1; j<=n; j++) 42 { 43 cin>>s[i][j]; 44 s[i][j]+=s[i-1][j]; 45 }//输入矩阵并且计算从(1,j)到(i,j)的矩阵的和值 46 int max=-INF,ans; 47 for(i=1; i<=n; i++) 48 for(j=i; j<=n; j++) 49 { 50 get_sum(i,j); 51 ans=DP(); 52 max=ans>max?ans:max; 53 } 54 printf("%d ",max); 55 } 56 return 0; 57 }