题目传送门: 题目链接
题目描述:
一个M*N的矩阵,找到此矩阵的一个子矩阵,并且这个子矩阵的元素的和是最大的,输出这个最大的值。 例如:3*3的矩阵:
-1 3 -1 2 -1 3 -3 1 2
和最大的子矩阵是:
3 -1 -1 3 1 2
Input
Output
Input示例
Output示例
|
解题思路:
LL a[N][N]; // a[i][j] 代表的第 i 行前j个数的和
a[i][j1] - a[i][j2] 代表的是 第i行 ,j1+1 到 j2 的连续字段和,例: a[1][3] - a[1][1] = a[1][2] + a[1][3],这种连续字段和一共 (m+1)*m/2 种。
然后将这些连续字段和看成一个元素,从 第1行 到 第n行 求最大连续字段和。
从所有的最大连续字段和中求得 最大值 就是 最大子矩阵和。
时间复杂度: m* (m+1)*m/2 空间复杂度:n^2
参考代码:
#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
const int N = 510;
// a[i][j] 代表的第 i 行前j个数的和
LL a[N][N];
int main()
{
int n, m;
cin >> m >> n;
// 初始化
memset(a, 0, sizeof(a));
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
cin >> a[i][j];
a[i][j] = a[i][j]+a[i][j-1];
}
}
// ans 为最大子矩阵和
int ans = a[1][1];
for(int i=0; i<m; i++) {
for(int j=i+1; j<=m; j++) {
// i到j 代表的是 每行 i+1 到 j 的连续字段和,这种连续字段和一共 (m+1)*m/2 种。
int temp = 0;
// 然后将这些 连续字段和 (a[k][j]-a[k][i) 看成一个元素,从 第1行 到 第n行 求最大连续字段和;
// 从所有的最大连续字段和中求得 最大值 就是 最大子矩阵和。
for(int k=1; k<=n; k++) {
temp += a[k][j]-a[k][i];
if(temp > ans) {
ans = temp;
}
if(temp < 0) {
temp = 0;
}
}
}
}
cout << ans << endl;
return 0;
}