PKU1050:To the Max

To the Max
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 21624 Accepted: 11192

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

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

Sample Output

15

原题地址:http://acm.pku.edu.cn/JudgeOnline/problem?id=1050

____________________________________________________________________________________________________________________________

题解

DP, 最大子字段和,最大子矩阵和。

方程不难,只是没遇到过。

  

1、最大子字段和

题目描述:给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a+a+…+a[j]的子段和的最大值。当所给的整均为负数时定义子段和为0,依此定义,所求的最优值为Max{0,a+a+…+a[j]},1<=i<=j<=n

题解:记b[j]=max(a+..+a[j-1]+a[j]),其中1<=i<=j,并且1<=j<=n。则所求的最大子段和为max b[j],1<=j<=n。

         由b[j]的定义可易知,当b[j-1]>0时b[j]=b[j-1]+a[j],否则b[j]=a[j]。故b[j]的动态规划递归式为:b[j]=max(b[j-1]+a[j],a[j]),1<=j<=n。

  

实际上本题要求的是子矩阵的和,可以由字段和推广得到

 

2、最大子矩阵和

矩阵是二维的,将其压缩成一维就可以用上面的方法求出最大子矩阵和了

B[I][J]表示第I列,自第一行加到第J行的和。那么B[I][J]-B[I][K]就是第I列中第K行加到第J行的和。

求第K行到第J行之间的最大子矩阵就只要对所有的A[I]=B[I][J]-B[I][K](1<=I<=N)做遍最大字段和就可以了。

  

DP,共三层循环。
最外层i循环1-M,表明子矩阵是从第i行开始累加的。
第二层j循环i-M,表明子矩阵是从第i行累加到第j行。
第三层k从1到N做一维DP。

 

 

代码:

 

代码
1 #include<stdio.h>
2  int compress[101][101],matrix[101][101],dp[101];
3  int i,j,k,n,max;
4  int main()
5 {
6 scanf("%d",&n);
7 for (i=1;i<=n;i++)
8 for (j=1;j<=n;j++)
9 scanf("%d",&matrix[i][j]);
10 for (i=1;i<=n;i++)
11 compress[1][i]=matrix[1][i];
12 for (i=2;i<=n;i++)
13 for (j=1;j<=n;j++)
14 compress[i][j]=compress[i-1][j]+matrix[i][j];
15 max=0;
16 for (i=1;i<=n;i++)
17 for (j=i;j<=n;j++)
18 {
19 dp[1]=compress[j][1]-compress[i-1][1];
20 for (k=2;k<=n;k++)
21 {
22 if (dp[k-1]>0) dp[k]=dp[k-1]+compress[j][k]-compress[i-1][k];
23 else dp[k]=compress[j][k]-compress[i-1][k];
24 if (dp[k]>max) max=dp[k];
25 }
26 }
27 printf("%d\n",max);
28 return 0;
29 }
30

 

posted on 2010-07-28 12:34  风也轻云也淡  阅读(955)  评论(2编辑  收藏  举报