美文网首页
最大子矩阵

最大子矩阵

作者: 碧影江白 | 来源:发表于2017-03-03 13:15 被阅读753次
                                            问题描述
      给定一个n*m的矩阵A,求A中的一个非空子矩阵,使这个子矩阵中的元素和最大。
    
      其中,A的子矩阵指在A中行和列均连续的一块。
    输入格式
      输入的第一行包含两个整数n, m,分别表示矩阵A的行数和列数。
      接下来n行,每行m个整数,表示矩阵A。
    输出格式
      输出一行,包含一个整数,表示A中最大的子矩阵中的元素和。
    样例输入
    3 3
    -1 -4 3
    3 4 -1
    -5 -2 8
    样例输出
    10
    样例说明
      取最后一列,和为10。
    数据规模和约定
      对于50%的数据,1<=n, m<=50;
      对于100%的数据,1<=n, m<=500,A中每个元素的绝对值不超过5000。
    

    之前学过最大子序列的求法:
    要求一个序列中和最大的连续的子序列,那么需要满足一下几步:
    1,子序列的第一个数大于1。
    2,从第一个大于0的数开始累加,不断记录最大的和。
    3,如果出现和小于0,那么说明负数值已经足够多,该记录不再继续,重新开始累加。
    总结成代码函数实现:

    int sub_sum(int *b)
    {
        int s,max;
        s = max = b[1];
        int i;
        for(i=2;i<=n;i++)
        {
            s += b[i];
            if(s > max)
                max = s;
            if(s < 0)
                s = 0;
        }
        return max;
    }
    
    

    而当最大子序列扩展为最大矩阵时,暴力破解必定是超时的,这时需要用到该知识点进行扩展从而求解。
    思路如下:
    1,所求的子矩阵必须是每一行数字个数都相等,每一列的数字个数也相等。
    2,假设都是固定的列数,可以将每一列都加和存入数组,那么得到的就是一个一维的数组,把这个数组求最大子序列即可。
    3,既然是在一个矩阵中求解的,所以子矩阵的列数范围在原矩阵的列数范围之内,用列举方法即可。
    具体图解如下:


    表示,从第一行,第一,二行,到从第一行到最后一行,每次都取各列的和存入数组,求解最大子序列。
    从第二行,第二,三行,到从第二行到最后一行,每次都取各列和存入数组,求最大子序列。
    一直到最后一行,求最大子序列。
    最大子序列中求解最大值,即是所求的解。

    整理成代码求解:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define N 501
    int a[N][N];
    int n,m;
    int sub_sum(int *b)//求最大子序列
    {
        int s,max;
        s = max = b[1];
        int i;
        for(i=2;i<=n;i++)
        {
            s += b[i];
            if(s > max)
                max = s;
            if(s < 0)
                s = 0;
        }
        return max;
    }
    int main()
    {
        int i,j,t,maxsum,s;
        int *b;
        scanf("%d%d",&n,&m);
        b = (int *)malloc(sizeof(int)*(n+1));
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++)
            {
                scanf("%d",&a[i][j]);
            }
        maxsum = a[1][1];
        for(i=1;i<=m;i++)
        {
            memset(b,0,(n+1)*sizeof(int));
            for(j=i;j<=m;j++)
            {
                //固定i,j列
                for(t=1;t<=n;t++)
                    b[t] += a[t][j];//自底向上(固定列m,m,n(固定行n,n,m))
                s = sub_sum(b);
                if(s > maxsum)
                    maxsum = s;
            }
        }
        printf("%d\n",maxsum);
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:最大子矩阵

          本文链接:https://www.haomeiwen.com/subject/ajikgttx.html