求和最大的子矩阵

/*求一个矩阵中最大的二维矩阵(元素和最大).如: 
1 2 0 3 4 
2 3 4 5 1 
1 1 5 3 0 
中最大的是: 
4 5 
5 3 
*/  
#include <limits>  
//假设寻找的子矩阵是大小为n的方阵,不限于二维。  
//先对行求和,得到矩阵sumMat[row-n+1][col],里面每个元素都对应了n行的和
//然后对sumMat的每行求最大的子序列(长度为n)

//子函数,预处理,对原始矩阵的行求和,输出辅助矩阵
static void addRow(const vector<vector<int> >& m,int n, vector<vector<double> >& sumMat) 
{
    int row = (int)m.size();
    int col = (int)m[0].size();
    sumMat.resize(row-n+1,vector<double> (col));

    for(int i=0; i < n; ++i)
    {
        for(int j=0; j < col;++j)
        {
            sumMat[0][j] += m[i][j];
        }
    }

    int idx = 0;
    for(int end= n; end < row; ++end)
    {
        for(int j=0; j < col;++j)
        {
            //注意下标
            sumMat[idx+1][j] = sumMat[idx][j] + m[end][j] - m[end-n][j];
        }
        idx++;
    }
}
//子函数,对每行计算最大序列的位置
static void calcMax(const vector<double>& sumArrary,int n,int &col, double& sum)
{
    sum=0;
    col = 0;
    for(int i=0; i < n; ++i)
    {
        sum+= sumArrary[i];
    }

    double max= sum;
    for(int i= n; i < sumArrary.size(); ++i)
    {
        sum += sumArrary[i] - sumArrary[i-n];
        if(sum > max)
        {
            col = i-n+1//注意是返回子序列的起始位置
            max = sum;
        }
    }
    sum = max;
}

bool calcMaxSubMatrix(const vector<vector<int> >& m,int n,double& sum, vector<vector<int> >& subMat) 
{
    int row = (int)m.size();
    int col = (int)m[0].size();
    if(n > row || n > col){return false;}  

    vector<vector<double> > sumMat;
    addRow(m,n,sumMat); //预处理

    double max= -DBL_MAX;
    int maxCol, maxRow;
    for(int i=0; i < sumMat.size(); ++i)
    {
        int col;
        double matSum;
        calcMax(sumMat[i],n,col,matSum);
        if(matSum > max)
        {
            max = matSum;
            maxCol = col;
            maxRow = i;
        }
    }

    sum = max;
    subMat.resize(n, vector<int> (n));    
    for(int i =0; i < n; ++i)    
    {    
        for(int j =0; j < n; ++j)    
        {    
            subMat[i][j] = m[maxRow+i][maxCol+j];    
        }    
    }    
        
    return true;  
}

static void fillVector(int* a,int row, int col, vector<vector<int> >& out)    
{    
    out.resize(row, vector<int> (col));    
    for(int i=0 ; i < row; ++i)    
    {    
        for(int j=0; j < col; ++j)    
        {    
            out[i][j] = a[i*col+j];    
        }    
    }    
}   
static void test1()    
{    
    vector<vector<int> > m;    
    int a[3][5] ={  {12034},
                    {23451},
                    {11530}};    
    fillVector(a[0],3,5,m);    
        
    vector<vector<int> > subM;    
    double sum;    
    calcMaxSubMatrix(m,2,sum,subM);    
    printf("sum=%g\n",sum);    
    for(size_t i=0 ; i < subM.size(); ++i)    
    {    
        for(size_t j=0; j < subM[i].size(); ++j)    
        {    
            printf("%d,", subM[i][j]);    
        }    
        printf("\n");    
    }    
}   

static void test2()    
{    
    vector<vector<int> > m;    
    int a[3][5] ={{12034},{23451},{1153,10}};    
    fillVector(a[0],3,5,m);    
        
    vector<vector<int> > subM;    
    double sum;    
    calcMaxSubMatrix(m,2,sum,subM);    
    printf("sum=%g\n",sum);    
    for(size_t i=0 ; i < subM.size(); ++i)    
    {    
        for(size_t j=0; j < subM[i].size(); ++j)    
        {    
            printf("%d,", subM[i][j]);    
        }    
        printf("\n");    
    }    
}    
void testCalcMaxSubMatrix()    
{    
    test1();    
    test2();    
}   
posted @ 2014-12-31 00:09  _pop  阅读(461)  评论(0编辑  收藏  举报