下面这个问题是数组的最大累加和问题的拓展
题目:
给定一个矩阵matrix,其中的值有正、有负、有0,返回子矩阵的最大累加和。 例如,矩阵matrix为:
-90 48 78
64 -40 64
-81 -7 66
其中,最大累加和的子矩阵为:
48 78
-40 64
-7 66
所以返回累加和209。
再例如,matrix为:
-1 -1 -1
-1 2 2
-1 -1 -1
其中最大累加和的子矩阵为:
2 2
所以返回累加和 4。
分析过程
如果穷举所有的子矩阵,由于所有的矩阵是(N*N)*(N*N)级别的,再判断最大值是N*N级别的;最后是N^6级别的。
优化一下,这道题要用到子数组的最大累加和问题,这里是求二维的最大和,我们可以把它降到一维的。
我们把行的维数用穷举法降了,即我们现在只关心一行的连续最大累加和。
比如
1 2 3
4 5 6
7 8 9
矩阵的最大累加矩阵只可能是1行的(3种情况,即第1、2、3行的最大累加行的最大值),2行的(2种情况,1、2行或者3,、4行的最大值),3行的(1种情况,本身).
我们比较这六种情况,求出最大值就行了。
这种算法的时间复杂度是N^3.(穷举的复杂度是N^2,得出一行的最大累加和的复杂度是N)
c/c++代码:
#include <iostream>
using namespace std;
//求一行的子数组最大累加和
int maxSubArray(int a[],int n)
{
int cur=0,max=-100000000;
for(int i=0;i<n;i++)
{
cur += a[i];
max = cur>max?cur:max;
cur = cur<0?0:cur;
}
return max;
}
int maxSubMatrix(int array[][3],int n)
{
int i,j,k,max=0,sum=-100000000;
int b[3];
for(i=0;i<n;i++)
{
for(k=0;k<n;k++)//初始化b[]
{
b[k]=0;
}
for(j=i;j<n;j++)//把第i行到第j行相加,对每一次相加求出最大值
{
for(k=0;k<n;k++)
{
b[k]+=array[j][k];
}
max=maxSubArray(b,k);
if(max>sum)
{
sum=max;
}
}
}
return sum;
}
int main()
{
int n=3;
int array[3][3]={{-1,2,0},{-1,-2,-3},{4,9,6}};
cout<<"MaxSum: "<<maxSubMatrix(array,n)<<endl;
}