Task 4.2 求一个矩阵的最大子矩阵的和

任务:输入一个二维整形数组,数组里有正数也有负数。二维数组中连续的一个子矩阵组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为O(n)。

(1)设计思想:把二维矩阵分解成行、列的情况,可以相应把问题简化。之后分别依照行和列的基准来求每一个矩阵的和,再依次进行比较每个矩阵的和。最容易想到也是最容易实现的方法。遍历矩阵(行迭代器为i,列迭代器为j),以当前遍历到的元素为首a[i,j],计算二维子矩阵的和(sum=a[i,j]+a[i+1,j]+a[i,j+1]+a[i+1,j+1]),并找出和最大的二维矩阵,注意矩阵的最后一行和最后一列不用遍历。时间复杂度为O(i*j)。

改进方法如下:

a.原先每次访问四个元素,现在变为每次访问纵向的两个元素(a[i,j],a[i+1,j]),横向遍历,遍历的起始点改为第二个元素,终点到最后一个元素。

b.改变求和方式,求和方法是:首先将上一次保存的和last_vsum加进sum中,再将last_vsum更新为当前纵向的两个元素a[i,j],a[i+1,j]之和,然后再将last_vsum加入sum中,这样就得到本次二维矩阵的和可与maxsum进行比较。如此每次求和只需访问两个元素a[i,j],a[i+1,j]。

(2)代码:

#include<iostream>
#include<time.h>
using namespace std;

void main()
{
    int m,n,a[100][100],k,t,c,i,j,z;
    int maxsum,sum[100],max=0;
    cout<<"请输入矩阵的行数和列数:"<<endl;
    cin>>m>>n;
    srand((unsigned)time(NULL));
    for(i=0;i<m;i++)
     {   
         for(j=0;j<n;j++)
         {
             a[i][j] = rand() %140 - 70;
             cout<<a[i][j]<< " ";
         }
         cout<<endl;
     }
        for(k=0;k<m;k++)
        {
            //初始化一个m*n型的二维数组,以作为储备每一个细化的子矩阵之和
            for(c=0;c<n;c++)
            {sum[c]=0;}
            //求此矩阵划分而得的每一个子矩阵之和
            for(j=k;j<n;j++)
            {
                for(i=0;i<m;i++)
                {
                    sum[i]+=a[i][j];
                }
                //依次比较所得到的每个子矩阵之和取最大子矩阵之和
                   for(t=0;t<m;t++)
                   {
                    maxsum=0;
                    for(z=t;z<n;z++)
                    {
                        maxsum+=sum[z];
                        if(maxsum>max)
                            max=maxsum;
                    }
                   }
            }
        }
       cout<<"最大子矩阵之和为:"<<max;
 
  
}


3.实验截图:

4.总结:(1)开始上课的时候就在找各种方法实现,比如找到矩阵中的最大和再扩展开求最大矩阵和;或是找出所有正数根据正数的个数和大小判断求出最大矩阵和;但是最终都没有得出一个完整的思路,因为都太难实现了而且总会有一些细节与期望值不相符。所以最后我们两个就重整思路写出了这个程序。

(2)要学会把一个复杂的项目分解,因为只有学会了分解以后才能更快更好地解决所有的问题。

posted @ 2015-04-08 22:35  mengxiangjialzh  阅读(430)  评论(1编辑  收藏  举报