给麦克斯
时限:1000 MS | 内存限制:10000 K | |
提交材料共计:51175 | 接受:27064 |
描述
给定一个二维的正和负整数数组,子矩形是任意大小1*1或更大的相邻子数组,位于整个数组中。矩形的总和是该矩形中所有元素的总和。在这个问题中,带最大总和的子矩形称为最大子矩形。
作为例子,数组的最大子矩形:
0-2-7 0
9 2-6 2
-4 1-4 1
-1 8 0-2
位于左下角:
9 2
-4 1
-1 8
并且有15张。
作为例子,数组的最大子矩形:
0-2-7 0
9 2-6 2
-4 1-4 1
-1 8 0-2
位于左下角:
9 2
-4 1
-1 8
并且有15张。
输入
输入由n*n数组组成。输入首先由一行上的一个正整数n开始,指示平方二维数组的大小。接下来是n^2整数,由空格分隔(空格和空格)。这些是数组的n^2整数,以行主顺序呈现。也就是说,第一行中的所有数字,左到右,然后所有的数字在第二行,左到右等。n可能高达100。数组中的数字将在[-127127]范围内。
输出量
输出最大子矩形的总和。
样本输入
4 0 -2 -7 0 9 2 -6 2 -4 1 -4 1 -1 8 0 -2
样品输出
15
来源
考查:动态规划 最大子段和
提交情况:一次AC
收获:又认识了下最大连续子段和
在一维情况下最大连续子段和的求法是从左到有顺序扫描数据,以0为边界,当累加和小于0时则重置为0.动态规划的状态转移方程为
s=max{si-1+ai,ai},该方程和前面的描述是等价的。本题是对一维最大子段和的扩展,思路是从上到下找出所有的连续行(如第i行到第j行),然后计算每列从第i行到第j行的和,之后对这n个列的和进行一维最大子段和的计算,并找出最大的值。
AC_CODE:
- #include <stdio.h>
- #define MAX 101
- int main()
- {
- int n;
- int a[MAX][MAX]={0};
- int colsum[MAX][MAX]={0};
- int max=0,sum;
- scanf("%d",&n);
- for(int i=0;i<n;i++)
- for(int j=1;j<=n;j++)
- {
- scanf("%d",&a[i][j-1]);
- colsum[i][j]=colsum[i][j-1]+a[i][j-1];
- }
- for(int i=0;i<n;i++)
- for(int j=i;j<=n;j++)//从第i行到第j行
- {
- sum=0;
- for(int k=0;k<n;k++)//每列的和
- {
- sum+=colsum[k][j]-colsum[k][i];
- if(sum<0) sum=0;
- else if(sum>max) max=sum;
- }
- }
- printf("%d/n",max);
- return 0;
- }