题目:从m*n矩阵中找出元素和最大的子矩阵。
分析:此题是可看做节课求和值最大子数组的一种延伸。但如果按之前的枚举法显然太过麻烦,复杂度为O(n^4)。那么有没有更好的方法呢?
我们拿出上一道题做了进一步的商讨。找了一些网上的思路得到了如下方法:
1 #include <iostream.h> 2 maxSubarray(int n,int a[]) 3 { 4 int b=0,sum=-100000; 5 for(int i=0;i<n;i++) 6 { 7 if(b>0) b+=a[i]; 8 else b=a[i]; 9 if(b>sum) sum=b; 10 } 11 return sum; 12 } 13 int main() 14 { 15 int a[]={-1,3,4,-6,5,3,7,-9,10,0}; 16 cout<<maxSubarray(10,a)<<endl; 17 }
此算法的原理是,按序一个个相加,正数越加越大,每得到一个正数更新一次sum;而负数越加越小,当和值为负时,放弃前面的数,更新b,寻找新一轮的正数最大和b,当大于前面的sum时赋给sum。for循环执行一遍,将最大值在b,sum之间动态传递和更新,时间复杂度O(n),与之前的穷举法相比无疑是一种高效的算法。
那么由此延伸到二维数组中,求矩阵的最大子矩阵和,我们得到如下算法:
1 #include <iostream.h> 2 int maxSubArray(int n,int a[]) 3 { 4 int b=0,sum=-10000000; 5 for(int i=0;i<n;i++) 6 { 7 if(b>0) b+=a[i]; 8 else b=a[i]; 9 if(b>sum) sum=b; 10 } 11 return sum; 12 } 13 int maxSub(int n,int array[][10]) 14 { 15 int i,j,k,max=0,sum=-100000000; 16 int b[10]; 17 for(i=0;i<n;i++) 18 { 19 for(k=0;k<n;k++)//初始化b[] 20 { 21 b[k]=0; 22 } 23 for(j=i;j<n;j++)//把第i行到第j行相加,对每一次相加求出最大值 24 { 25 for(k=0;k<n;k++) 26 { 27 b[k]+=array[j][k]; 28 } 29 max=maxSubArray(k,b); 30 if(max>sum) 31 { 32 sum=max; 33 } 34 } 35 } 36 return sum; 37 } 38 void main() 39 { 40 int n,array[10][10]; 41 cout<<"输入矩阵行列数"; 42 cin>>n; 43 cout<<"\n输入矩阵"<<endl; 44 for(int i=0;i<n;i++) 45 { 46 for(int j=0;j<n;j++) 47 { 48 cin>>array[i][j]; 49 } 50 } 51 cout<<"子矩阵元素和最大为"<<maxSub(n,array)<<endl; 52 }