POJ 1050 To the Max

To the Max
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 36422   Accepted: 19130

Description

Given a two-dimensional array of positive and negative integers, a sub-rectangle is any contiguous sub-array of size 1*1 or greater located within the whole array. 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.  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 corner: 
9 2  -4 1  -1 8  and has a sum of 15. 

Input

The input consists of an N * N array of integers. The input begins with a single positive integer N on a line by itself, indicating the size of the square two-dimensional array. This is followed by N^2 integers separated by whitespace (spaces and newlines). These are the N^2 integers of the array, presented in row-major order. That is, all numbers in the first row, left to right, then all numbers in 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

Output the sum of the maximal sub-rectangle.

Sample Input

4
0 -2 -7 0 9 2 -6 2
-4 1 -4  1 -1

8  0 -2

Sample Output

15

传说中经典的DP问题,昨天比赛时为了解一道看起来类似的题直接网搜了此题的结题报告,发现暴力转化为一维数组求最长子序列的思想果然高明(可是比赛那道题还是TLE了T^T)
二维数组转化以为数组举例:
0 -2 -7 0
9 2 -6 2
可以转化为:
9 0 -13 2
也就是把纵向的一列求和,然后再求最大子序列和即为这个最大子矩阵的和

求最大子序列和用了一点DP思想,DP之前也没怎么写过,每次想DP总想着区间,这里的DP是用点来做的
用一个数组f[i]代表数组s中以s[i]结尾的最大子序列的和,这样得到了状态转移方程:
f[i]=f[i-1]+f[i]>f[i]?f[i-1]+f[i]:f[i];

代码如下:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 
 5 using namespace std;
 6 
 7 long g[101][101];
 8 long s[101];
 9 long f[101];
10 
11 long FindMax(int n)
12 {
13     memset(f,0,sizeof(f));
14     for(int i=1;i<=n;i++)
15         f[i]=(f[i-1]+s[i]>s[i]?f[i-1]+s[i]:s[i]);
16     long maxn=f[1];
17     for(int i=2;i<=n;i++)
18         if(f[i]>maxn)
19             maxn=f[i];
20     return maxn;
21 }
22 
23 int main()
24 {
25     int n;
26     long ans,result;
27 
28     while(scanf("%d",&n)==1)
29     {
30         for(int i=1;i<=n;i++)
31             for(int j=1;j<=n;j++)
32                 scanf("%ld",&g[i][j]);
33         for(int len=1;len<=n;len++)
34         {
35             for(int y=1;y<=n-len+1;y++)
36             {
37                 for(int x=1;x<=n;x++)
38                     s[x]=0;
39                 for(int x=1;x<=n;x++)
40                     for(int t=y;t<y+len;t++)
41                         s[x]+=g[x][t];
42                 result=FindMax(n);
43                 if(len==1&&y==1)
44                     ans=result;
45                 else
46                     if(ans<result)
47                         ans=result;
48             }
49         }
50         printf("%ld\n",ans);
51     }
52 
53     return 0;
54 }
[C++]

 

posted @ 2013-07-12 11:05  ~~Snail~~  阅读(151)  评论(0编辑  收藏  举报