Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 49226 | Accepted: 26074 |
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
4 0 -2 -7 0 9 2 -6 2 -4 1 -4 1 -1 8 0 -2
Sample Output
15
翻译
给出一个有正整数和负整数的二维的向量,附属矩阵是在向量中数个矩形就是其附属矩形,(>1*1),附属矩形的和是各个元素的和
IN
第一行:N代表这个N*N矩阵的维数
接下来几行输入16个整数,以空白符相隔无论是space还是tab还是enter
OUT
第一行(最有一行):附属矩形和的最大数
第一行:N代表这个N*N矩阵的维数
分析:
在做这道题之前必须会最大字段和这一道题的基础,这也是动态规划中最简单的一道例题,而这道题是最大字段和的一个扩展。
例子: 0,2,7,2,-5最大的一个连续子序列之和。
分析:这五个数有这样几种和的组合:0;02;027;0272;……这样5!个数。
用数组索引来表示就是:0;0到1;0到2;0到3……1;1到2;……(这里是数组索引表示)
我们显然不能用多重循环把所有数都算出来,我们换一种角度思考,如果只有一个数字,那么最大的连续子序列数多少,还是以上面的例子为例,应该是0吧,那么现在有两个数字呢?有两种情况,一种是前面有一个数字的最大值(已求)+现在这个数字;另外一种情况是就是只有这个数字;然后算出来的最大值与只有一个数字的情况的最大值相比较;现在有三个数字,也有两种情况,一种是前面有前面两个数字的最大值+现在这个数字;或者就是只是这个数字;……
代码:
第一行:N代表这个N*N矩阵的维数
- int max_sum(int n)
{
int i, sum = 0, max = INT_MIN;
for(i = 0; i < n; i++)
{ -------------------------------------------------------------------------------0
if(sum < 0)
sum = 0;
sum += a[i]; ---------------------------------------------------------1
if(sum > max)
max = sum;---------------------------------------------------------2
}
return max;
}
上面把文字变成代码就是我们普通程序员做的事情,文字表述部分就是大神们做的事情。
算了,不哭了,我来解释一下为什么文字翻译成了一样一些代码。
----0----代表蓝色部分【这个不用说循环】
----1----代表橙色部分【**下面说**】
----2----代表紫色部分
我们橙色的字;因为一共有两种情况,一种是自己本身,一种是前i-1项的最大值,我们换个思路想一下,假如第1个数(索引为0的数)为负数,那么下面前两个数的最大最一定是第二个数其本身,即第二次是把sum=0;sum+=a[1] 然后记录max值。。。实际上就是假如你前n个数是正的那么可以继续加上去,如果你前n个数是负的那么把值记录一下就好了。所以只要求前n项和和最大值就好了。
当然也有人是这样写的:
- int MaxSum(int n,int *a)
- {
- int sum=0,b=0;
- for(int i=1; i<=n; i++)
- {
- if(b>0)
- {
- b+=a[i];
- }
- else
- {
- b=a[i];
- }
- if(b>sum)
- {
- sum = b;
- }
- }
- return sum;
- }
或者更加直白的话是这样写的,这样更加容易理解一些,看个人的编程习惯了
- int max_sum2(int n)
{
b[0]=a[0]; //数组b存放前n项的最大值
int maximal=b[0];
for(int i=1;i<n;i++)
{
b[i]=max(b[i-1]+a[i],a[i]); //STL
if(b[i]>maximal)
maximal=b[i];
}
return maximal;
}
代码:
#include<iostream>
#include<algorithm>
using namespace std;
const int MAX=101;
int arr[MAX][MAX]={0};
int Dy[MAX][MAX]={0};
int main(){
int N;
cin>>N;
for(int i=1;i<=N;i++)
{
for(int j=1;j<=N;j++)
{
cin>>arr[i][j];
Dy[i][j]=Dy[i][j-1]+arr[i][j]; //让Dy存放第i行的前j项和
//其实我们用数学之美来看为什么要这样存放,你一维的时候存放的是一维的数据
//二维的时候再存放一维的数据就是错误的,二维的时候就应该存放二维的数据
//当然你也不要去存放前i行前j列之和,这个相比于前面的就是三维的数据了
//如果你算的是长方体的数据,这样应该是对的,那么我们的数组也应该是三维的了
}
}
int max=INT_MIN;
int sum;
for(int i=1;i<=N;i++)
{
for(int j=i;j<=N;j++)
{
sum=0;
//前面两层循环是列循环,比如三列的话就是,1-2列,1-3列,2-3列
for(int k=0;k<=N;k++)
{
//行循环,求和
if(sum<0) sum=0;
sum+=(Dy[k][j]-Dy[k][i-1]);
if(sum>max) max=sum;
}
}
}
cout<<max<<endl;
}