最大子矩阵和

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最大子矩阵和相关的知识,希望对你有一定的参考价值。

 问:给定一个N*M的矩阵,其子矩阵有2^(M*N)个子矩阵,将子矩阵中的每个元素求和,求和最大的子矩阵。

我们可以枚举每个子矩阵,时间复杂度为0(2^(M*N)),该方法是不可行的。我们之前遇到过一个一维数组中最大子段和的问题。其状态转移方程为 if(b[i-1]>0) b[i]=b[i-1]+a[i] else b[i]=a[i],

其时间复杂度为0(N),代码如下:

int MaxSubSegSum(int num[])
{
    int b[MAXN],maxn;
    maxn=b[0]=num[0];
    for(int i=1;i<m;i++)
    {
        if(b[i-1]>0)    b[i]=b[i-1]+num[i];
        else    b[i]=num[i];
        maxn=max(maxn,b[i]);
    }
    return maxn;
}

 

 我们可以这样想:我们任意取第i行到第j行列全包含的子矩阵。我们将每行求和,转化为求最大子段和问题。我们就可以在O(M)的时间内枚举M*(M+1)/2个子矩阵,而这样的列全包含矩阵有

N*(N+1)/2 个。这样我们就可以在O(N*N*M)的时间内求得,这样大大降低了时间复杂度。

完整代码如下:

#include"cstdio"
#include"cstring"
#include"algorithm"
using namespace std;
const int MAXN=1005;
int n,m;
int matrix[MAXN][MAXN];
int l,r,up,down;
int ll,rr;
int lll,rrr;
int MaxSubSegSum(int num[])
{
    int b[MAXN],maxn;
    maxn=b[0]=num[0];
    l=r=0;
    for(int i=1;i<m;i++)
    {
        if(b[i-1]>0)
        {
            b[i]=b[i-1]+num[i];
            r=i;
        }
        else
        {
            b[i]=num[i];
            r=i;
            l=i;
        }
        if(maxn<b[i])
        {
            maxn=b[i];
            ll=l;
            rr=r;
        }
    }
    return maxn;
}
int total[MAXN][MAXN];
int MaxSubMat()
{
    for(int j=0;j<m;j++)    total[0][j]=matrix[0][j];
    for(int i=1;i<n;i++)
        for(int j=0;j<m;j++)
        {
            total[i][j]=matrix[i][j];
            total[i][j]+=total[i-1][j];
        }
    int maxn=-0x3fffffff;
    int temp[MAXN];
    for(int i=0;i<n;i++)
    {
        for(int j=i;j<n;j++)
        {
            for(int z=0;z<m;z++)
            {
                if(i==0)    temp[z]=total[j][z];
                else    temp[z]=total[j][z]-total[i-1][z];
            }
            if(MaxSubSegSum(temp)>maxn)
            {
                maxn=MaxSubSegSum(temp);
                up=i;
                down=j;    
                lll=ll;
                rrr=rr;
            }
        }
    }
    return maxn;
}
int main()
{
    scanf("%d%d",&m,&n);
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)    scanf("%d",&matrix[i][j]);
    int ans=MaxSubMat();
    printf(" 最大子矩阵为:\n");
    for(int i=up;i<=down;i++)
    {
        for(int j=lll;j<=rrr;j++)    printf("%d ",matrix[i][j]);
        printf("\n");
    }
    printf("其和为:%d\n",ans);
    return 0;
}
/*
3 3
-1 3 -1
2 -1 3
-3 1 2

3 -1
-1 3
1 2
7
*/

 

以上是关于最大子矩阵和的主要内容,如果未能解决你的问题,请参考以下文章

华为OD机试 -最大子矩阵和(Python) | 机试题+算法思路+考点+代码解析 2023

最大连续子矩阵和算法

最大子矩阵和

动态规划---例题4.最大子矩阵和问题

算法小总结最大连续子序列和最大连续子矩阵的关系与实现

左神算法课二维矩阵的子矩阵最大累加和