[每日一题]:最大子矩阵和

题目:

一个M*N的矩阵,找到此矩阵的一个子矩阵,并且这个子矩阵的元素的和是最大的,输出这个最大的值。

例如:3*3的矩阵:

-1 3 -1
2 -1 3
-3 1 2

和最大的子矩阵是:

3 -1
-1 3
1 2

题目链接:

https://www.51nod.com/Challenge/Problem.html#problemId=1051

最大子段和:

建议不了解我的先戳一下

侃侃:

这个题是 最大子段和的 二维升级版,如何将二维的降为一维的呢?
想一下,如果我们将 所有的一行压缩成一行,那么是不是就是我们
求的最大子段和了。

分析:

预处理行和列,进行压缩,得到每一列的前缀和。
枚举行。
接下来跟求最大子段和类似,进行求即可。

Code:

#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>

#define INF 0x3f3f3f3f

using namespace std;

typedef long long LL;

const int maxn = 505;

LL dp[maxn][maxn];

LL a[maxn];

int n,m;

LL value;

int main(void) {
	scanf("%d%d",&m,&n);
	for(int i = 1; i <= n; i ++) {
		for(int j = 1; j <= m; j ++) {
			scanf("%lld",&value);
			// 预处理,进行压缩 
			dp[i][j] = dp[i - 1][j] + value;
		}
	}
	
	LL ans = -INF;
	
	for(int i = 1; i <= n; i ++) {
		for(int j = i; j <= n; j ++) {
			LL num = 0;
			// 我们将几行压缩成了一行,就成了求最大子段和 
			for(int k = 1; k <= m; k ++) {
				num += dp[j][k] - dp[i - 1][k];
				if(num < 0) num = 0;
				if(num > ans) ans = num;
			}
		}
	}
	cout << ans << endl;
	return 0;
}
posted @ 2020-05-04 20:37  IceSwords  阅读(188)  评论(0编辑  收藏  举报