问题描述:
Description
给定一个n*m的矩阵A,求A中的一个非空子矩阵,使这个子矩阵中的元素和最大。其中,A的子矩阵指在A中行和列均连续的一块。
Input
输入的第一行包含两个整数n, m,分别表示矩阵A的行数和列数。
接下来n行,每行m个整数,表示矩阵A。
(1 <= n, m <= 50,1 <= n, m <= 500,A中每个元素的绝对值不超过5000)
Output
输出一行,包含一个整数,表示A中最大的子矩阵中的元素和。
Sample Input
3 3-1 -4 33 4 -1-5 -2 8
Sample Output
10
分析:当m,n的数据在100左右,可以直接利用求一维数组的最大连续区间方法直接搞定。但是当数据量达到500就必定超时,那么就必须使用二维数组记录这列的和,例如第i行第j列,必须记录下从0行到当前行对应的j列的和,sum[i][j]=a[0][j]+....+a[i][j]。
当1<=n,m<=100时可用这个方法(适合小数据)
AC代码:
当1<=n,m<=500时,以上代码会超时,至于两组代码的差距(即优化)当你看懂了自然就明白了。
AC代码:
分析:当m,n的数据在100左右,可以直接利用求一维数组的最大连续区间方法直接搞定。但是当数据量达到500就必定超时,那么就必须使用二维数组记录这列的和,例如第i行第j列,必须记录下从0行到当前行对应的j列的和,sum[i][j]=a[0][j]+....+a[i][j]。
当1<=n,m<=100时可用这个方法(适合小数据)
AC代码:
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=600,inf=-1000000000;
int a[maxn][maxn];
int n,m;
long long mergesort()
{
long long sum=inf;
long long key;
for(int i=1;i<=n;i++)
for(int j=0;j<=n-i;j++)
{
long long temp=inf;
for(int k=m-1;k>=0;k--)
{
key=0;
for(int x=j;x<=j+i-1;x++)
{
key+=a[x][k];
}
temp=max(key,temp+key);
sum=max(temp,sum);
}
}
return sum;
}
int main(void)
{
cin>>n>>m;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
cin>>a[i][j];
}
cout<<mergesort()<<endl;
return 0;
}
当1<=n,m<=500时,以上代码会超时,至于两组代码的差距(即优化)当你看懂了自然就明白了。
AC代码:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=505,inf=-100000000;
int a[maxn][maxn],sum[maxn][maxn];
int n,m;
int cur;
int solve()
{
cur=inf;
for(int i=0;i<=n;i++)
for(int j=i+1;j<=n;j++)
{
int temp=inf;
for(int k=m;k>=1;k--)
{
int x=sum[j][k]-sum[i][k];
temp=max(x,x+temp);
cur=max(cur,temp);
}
}
return cur;
}
int main(void)
{
cin>>n>>m;
memset(sum[0],0,sizeof(sum[0]));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
sum[i][j]=sum[i-1][j]+a[i][j];
}
cout<<solve()<<endl;
return 0;
}