最大子矩阵和

1. 简述

    给定一个n*n(0<n<=100)的矩阵,请找到此矩阵的一个子矩阵,并且此子矩阵的各个元素的和最大,输出这个最大的值。
    Example:
     0 -2 -7  0
     9  2 -6  2
    -4  1 -4  1
    -1  8  0 -2
    最大子矩阵为:
    9 2
   -4 1
   -1 8

2. 原理

    最大子矩阵和是最大子序列和的二维扩展。
    穷举所有子矩阵的话,有C(n,2)*C(n*2)/2个子矩阵,就是n^4个子矩阵,这还不算每个子矩阵求和的时间,就到了O(n^4)。
    转化为最大子序列求解的思路是:固定第i列到第j列的范围,寻找在这个范围内的最大子矩阵,这个寻找过程,把每行第i列上的元素到第j列的元素分别求和,就转变为了一维的情况。由于有C(n,2)种列的组合,而求一维的子序列需要n的时间,所以,总体上时间复杂度为O(n^3)。

3. 递推公式

    A的下标从0开始,为了增加哨兵,F,P,Q的下标都从1开始。    
    · A[N][N]表示输入矩阵。
    · F[N+1][N+1],F[i][j]表示从第i行的第0列到第j列的元素和。
    F[i][j]=0,j=0
      F[i][j]=A[i-1][j-1], j=1
      F[i][j]=F[i][j-1]+A[i-1][j-1],j>1
      这样当固定第i列到第j列的时候,转化为一维数组的第k个元素就可以表示为F[K][j]-F[K][i-1],K是行下标,i和j都是列下标,由于矩阵的统计是从1开始的,所以i,j,k都是大于等于1的,即i-1不会下标越界,这就是前面哨兵的作用。
    固定i列和j列的时候的求解递推公式:
    · P[N+1],P[k]表示固定第i列到第j列时,从第1行到第k行范围内,包括第k行的最大子矩阵。
    · Q[N+1],Q[k]表示固定第i列到第j列时,从第1行到第k行范围内,最大子矩阵。
      P[k]=F[0][j]-F[0][i-1], k=1
      P[k]=P[k-1]>0?(P[k-1]+F[k][j]-F[k][i-1]):(F[k][j]-F[k][i-1]),k>1
      Q[k]=P[k], k=1
      Q[k]=max{Q[k-1], P[k]}, k>1
      Q[N]即为固定列(i-j)范围内的最大和。

4. 代码   

#include <iostream>
using namespace std;
#define N 4
int main() {
  
int A[N][N] = { 0-2-7,  092-62-41-41-180-2 }; 
  
int F[N+1][N+1];
  
int P[N+1];
  
int Q[N+1];
  
int max, index_i, index_j;
  
// F 
  for(int i=1; i<N+1; i++) {
    F[i][
0= 0// 第0列,即哨兵列 
    F[i][1= A[i-1][0]; // 第1列 
  }
  
for(int i=1; i<N+1; i++) {
    
for(int j=2; j<N+1; j++) { // 从第2列开始 
      F[i][j] = F[i][j-1+ A[i-1][j-1];
    }
  }
  
// P,Q
  max = INT_MIN;
  
for(int i=1; i<N+1; i++) {
    
for(int j=i+1; j<N+1; j++) {
      P[
1= F[1][j]-F[1][i-1];
      Q[
1= P[1];
      
for(int k=2; k<N+1; k++) {
        P[k] 
= P[k-1]>0?(P[k-1]+F[k][j]-F[k][i-1]):(F[k][j]-F[k][i-1]);
        Q[k] 
= Q[k-1]>P[k]?Q[k-1]:P[k]; 
      }
      
if(Q[N] > max) {
        max 
= Q[N];
        index_i 
= i;
        index_j 
= j;
      }
    }
  }
  
// max
  cout << max << endl;
  cout 
<< index_i << " , " << index_j << endl;
  system(
"PAUSE");
  
return 0;

    输出结果如下:
   

5. 参考

    最大子矩阵问题    http://www.cnblogs.com/fll/archive/2008/05/17/1201543.html

posted @ 2011-09-02 12:17  xiaodongrush  阅读(10571)  评论(2编辑  收藏  举报