求N*M矩阵中的最大子矩阵和
一、问题描述
求N* M矩阵中子矩阵的最大元素和
二、分析
- 先计算出以左上角的元素(1,1)和当前元素(i,j)为顶点对的子矩阵的部分和,部分和的计算如下
PS[i][j] = A[i][j]+PS[i-1][j]+PS[i][j-1]-PS[i-1][j-1]
- 假设
已经确定了矩阵区域的上下边界
,不如知道矩阵区域的上下边界分布是第a行和第c行,接下来要确定左右边界。 - 我们
把第a行和第c行之间的每一列看成一个整体,相当于一维数组中的一个元素
(通过子矩阵部分和可以在O(1)时间内计算出整体之和)。
三、代码
#include <iostream>
#include <algorithm>
#define MAXN 1003
using namespace std;
int A[MAXN][MAXN];
long long PS[MAXN][MAXN];
inline long long MatrixSum(int s, int t, int i, int j)
{
return PS[i][j] - PS[i][t - 1] - PS[s - 1][j] + PS[s - 1][t - 1];
}
int main()
{
int m, n, i, j;
cin >> n >> m;
for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
cin >> A[i][j];
for (i = 0; i <= n; i++)
PS[i][0] = 0;
for (j = 0; j <= m; j++)
PS[0][j] = 0;
// 计算矩阵的部分和
for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
PS[i][j] = A[i][j] + PS[i - 1][j] + PS[i][j - 1] - PS[i - 1][j - 1];
int a, c;
long long All = A[1][1];
for (a = 1; a <= n; a++)
for (c = a; c <= n; c++)
{
// 将子矩阵上下边界设为第a行和第c行,在这些子矩阵中取最大值
long long Tail = MatrixSum(a, 1, c, 1);
for (j = 2; j <= m; j++)
{
Tail = max(MatrixSum(a, j, c, j),
MatrixSum(a, j, c, j)+Tail);
All = max(Tail, All);
}
}
cout << All;
}
求矩阵中元素之和最大的n行m列的子矩阵的元素之和
四、问题描述
找到整数矩阵matrix中,元素之和最大的n行m列的子矩阵的元素之和
五、代码
int maxSubmatrixSum(std::vector<std::vector<int>> matrix,int n, int m)
{
int base_sum = 0;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
base_sum += matrix[i][j];
}
}
int result = 0;
for (int i = 0; i + n - 1 < matrix.size(); i++)
{
if(i > 0)
{
for (int y = 0; y < m; y++)
{
base_sum += matrix[i + n - 1][y] - matrix[i - 1][y];
}
}
int real_sum = base_sum;
if (real_sum > result)
{
result = real_sum;
}
for (int j = 0; j + m < matrix[i].size(); j++)
{
for (int x = i; x < i + n; x++)
{
real_sum += matrix[x][j + m] - matrix[x][j];
}
if (real_sum > result)
{
result = real_sum;
}
}
}
return result;
}