求和最大的子矩阵
/*求一个矩阵中最大的二维矩阵(元素和最大).如:
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] ={ {1, 2, 0, 3, 4},
{2, 3, 4, 5, 1},
{1, 1, 5, 3, 0}};
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] ={{1, 2, 0, 3, 4},{2, 3, 4, 5, 1},{1, 1, 5, 3,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();
}
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] ={ {1, 2, 0, 3, 4},
{2, 3, 4, 5, 1},
{1, 1, 5, 3, 0}};
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] ={{1, 2, 0, 3, 4},{2, 3, 4, 5, 1},{1, 1, 5, 3,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();
}