题目:《程序员面试金典(第5版)》P348
给定一个正整数和负整数组成的N*N矩阵,编写代码找出元素总和最大的子矩阵。
提示:按照书本P350的优化后的解法,借鉴了“连续子数组的最大和” 的思想,时间复杂度为O(n^3)。
//结构result是函数MaxSubMatrix()返回的数据类型
struct result
{
int rows;//子矩阵的行数
int cols;//子矩阵的列数
int x;//子矩阵左上角的点的行数
int y;//子矩阵左上角的点的列数
result(){ rows = 0; cols = 0; x = -1; y = -1; }
};
//求数组a的最大连续子数组和,res_start返回最大连续子数组的开头位置,res_end返回结尾位置,res_sum返回最大的和
void MaxSubArraySum(vector<int> a, int &res_start, int &res_end, int &res_sum)
{
res_start = 0;
res_end = a.size();
res_sum = a[0];
int sum = a[0];
int biggest = a[0];
for (int i = 1; i < a.size(); i++)
{
if (sum <= 0)
{
sum = a[i];
if (biggest < sum)
{
res_start = i;
res_end = i;
biggest = sum;
}
}
else
{
sum += a[i];
if (biggest < sum)
{
res_end = i;
biggest = sum;
}
}
}
res_sum = biggest;
}
//输入的矩阵m是N*N的方阵
result MaxSubMatrix(vector<vector<int>> m)
{
result res;
if (m.empty() || m[0].empty() || m.size() != m[0].size())
return res;
int N = m.size();
int biggestsum = m[0][0];
res.cols = 1; res.rows = 1; res.x = 0; res.y = 0;
for (int rowstart = 0; rowstart < N; rowstart++)
{
for (int rowend = rowstart; rowend < N; rowend++)
{
vector<int> tmp;
int cola, colb, cursum, SumOfCols = 0;
for (int coltmp = 0; coltmp < N; coltmp++)
{
SumOfCols = 0;
for (int j = rowstart; j <= rowend; j++)
{
SumOfCols += m[j][coltmp];
}
tmp.push_back(SumOfCols);
}
MaxSubArraySum(tmp,cola, colb, cursum);
if (cursum > biggestsum)
{
biggestsum = cursum;
res.rows = rowend - rowstart + 1;
res.cols = colb - cola + 1;
res.x = rowstart;
res.y = cola;
}
}
}
return res;
}