ural 1146. Maximum Sum(动态规划)

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

inputoutput
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 }
View Code

思路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 }
View Code
原文地址:https://www.cnblogs.com/zhangchengbing/p/3306060.html