zoukankan      html  css  js  c++  java
  • 最大子矩阵和

    求一个M*N的矩阵的最大子矩阵和。找出在矩阵中,所有元素加起来之和最大的子矩阵
    比如在如下这个矩阵中:
    0 -2 -7 0
    9 2 -6 2
    -4 1 -4 1
    -1 8 0 -2 
    拥有最大和的子矩阵为:
    9 2
    -4 1
    -1 8
    其和为15。

    思路:首先我们考虑如果是一维数组,我们要找到其中的最大子段和,应该怎么做。我们要记录从头到当前位置的最大字段和的值,如何计算这个值呢。比如第n个位置处的最大字段和,就是比较下第n-1位置处(前n-1个的最大字段和)的值,与当前位置的值。一共有两种情况:第一种情况是前n-1个的最大字段和加上当前值比较大,另一种情况是当前值比较大。我们都可以根据最大子段和问题的递推公式是 b[j]=max{b[j-1]+a[j], a[j]},b[j] 指的是从0开始到j的最大子段和。假设原始矩阵为:[9, 2, -6, 2], 那么b[] = {9, 11, 5, 7}, 那么最大字段和为11, 如果找最大子矩阵的话,那么这个子矩阵是 [9, 2]。

    int maxSubsequence(int arr[],int length)
    {  
                if (length== 0) {  
                    return 0;  
                }  
                int max = INT_MIN;  
                int *maxSub = new int[length];  
                maxSub[0] = arr[0];  
                  
                for (int i = 1; i < length; i++) {  
                    maxSub[i] = (maxSub[i-1] > 0) ? (maxSub[i-1] + arr[i]) : arr[i];   
                    if (max < maxSub[i]) {  
                        max = maxSub[i];  
                    }  
                }  
                return max;  
    }

    如果是二维的情况,就变成了最大子矩阵了。为了能够找出最大的子矩阵,我们需要考虑所有的情况。假设这个子矩阵是 2 *k, 也就是说它只有两行,要找出最大子矩阵,我们要从左到右不断的遍历才能找出在这种情况下的最大子矩阵。如果我们把这两行上下相加,情况就和求“最大子段和问题” 又是一样的了。

    为了找出在原始矩阵里的最大子矩阵,我们要遍历所有的子矩阵的可能情况,也就是说,我们要考虑这个子矩阵有可能只有1行,2行,。。。到n行。而在每一种情况下,我们都要把它所对应的矩阵部分上下相加才求最大子矩阵(局部)。

    为了能够在原始矩阵里很快得到从 i 行到 j 行 的上下值之和,我们这里用到了一个辅助矩阵,它是原始矩阵从上到下加下来的。

    total矩阵就是我们的辅助矩阵,total[i][j]表示从i行到j行的和

    int total[4][4];  
    memcpy(&total[0][0],&matrix[0][0],64); //新建total辅助矩阵,用原始矩阵初始化
    for (int i = 1; i < 4; i++)//4表示矩阵的行数
     {  
        for (int j = 0; j < 4; j++) //4表示矩阵的列数
        {  
            total[i][j] += total[i-1][j]; //将矩阵的对应每列从上到下加下来
        }  
    }  

    如果我们要求第 i 行到第 j 行之间上下值的和,我们可以通过total[j][k] - total[i-1][k] 得到,k对应的是第k列

    int subMaxMatrix(int matrix[4][4]) //这里直接传原始矩阵
    {  
                  
        int total[4][4];  
        memcpy(&total[0][0],&matrix[0][0],64);//建立辅助矩阵并初始化
        for (int i = 1; i < 4; i++)
         {  
            for (int j = 0; j < 4; j++) 
            {  
                total[i][j] += total[i-1][j]; //将矩阵的每一列从上到下加起来
            }  
        }  
                  
        int maximum =INT_MIN;  
        for (int i = 0; i < 4; i++)
        {  
            for (int j = i; j < 4; j++) 
            {  
            //result 保存的是从 i 行 到第 j 行 所对应的矩阵上下值的和  
                int* result = new int[4];  
                for (int f = 0; f < 4; f++)
                {  
                    if (i == 0) 
                        result[f] = total[j][f];//第一行就是本身 
                    else  
                        result[f] = total[j][f] - total[i - 1][f]; //其他行要减去起始行的结果才行,这样才是从起始行到该行的元素和
                }  
                int maximal = maxSubsequence(result,4);//求每个小矩阵对应一维数组的最大字段和
                if (maximal > maximum)
                    maximum = maximal;  
            }  
        }            
        return maximum;  
    }                     
  • 相关阅读:
    Android游戏开发22:Android动画的实现J2me游戏类库用于Android开发
    android sqlite SQLiteDatabase 操作大全 不看后悔!必收藏!看后精通SQLITE (第三部分,完整代码)
    使用OGR创建dxf格式矢量数据
    mysql 数据库引擎 MyISAM InnoDB 大比拼 区别
    android sqlite SQLiteDatabase 操作大全 不看后悔!必收藏!看后精通SQLITE (第二部分)
    mysql 更改数据库引擎
    android sqlite SQLiteDatabase 操作大全 不看后悔!必收藏!看后精通SQLITE (第一部分)
    android 数字键盘使用
    MySQL Innodb数据库性能实践
    eclipse : Error while performing database login with the driver null
  • 原文地址:https://www.cnblogs.com/mini-coconut/p/9283654.html
Copyright © 2011-2022 走看看