避免使用暴力枚举的方法,我们参考一维数组的求法,一维的解答可以再线性时间 内完成,具体可以参考我的编程珠玑读书笔记。
我们把问题从二维转坏为一维,现在我们枚举矩阵的上下边界,然后用一维的方法确定左右边界,时间复杂度为O(N^2*M)。
#include <iostream>
#include <cstring>
using namespace std;
const int maxn=505;
int matrix[maxn][maxn];
int ps[maxn][maxn]; //部分和
int maxnum=-0xfffff;
int mmax(int a,int b)
{
return a>b?a:b;
}
int BC(int row,int col,int m) //第row行到第col行之间的第m列所有元素之和
{
return ps[col][m]-ps[row-1][m]-ps[col][m-1]+ps[row-1][m-1];
}
int maxsum(int matrix[maxn][maxn],int n,int m)
{
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++)
{
int maxendinghere=0,maxsofar=0; //这是求解一维时的情形
for(int k=1;k<=m;k++)
{
maxendinghere=mmax(maxendinghere+BC(i,j,k),0);
maxsofar=mmax(maxsofar,maxendinghere);
}
if(maxsofar>maxnum)maxnum=maxsofar;
}
return maxnum;
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>matrix[i][j];
memset(ps,0,sizeof(ps));
for(int i=1;i<=n;i++) //部分和预处理矩阵,便于在O(1)的时间内得到BC()
for(int j=1;j<=m;j++)
ps[i][j]=ps[i-1][j]+ps[i][j-1]-ps[i-1][j-1]+matrix[i][j];
cout<<maxsum(matrix,n,m)<<endl;
return 0;
}