PKU1050:To the Max
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 21624 | Accepted: 11192 |
Description
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
Output
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
题解:记b[j]=max(a
由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)做遍最大字段和就可以了。
代码:
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