Codeup动态规划专题总结:最大子矩阵

问题 E: 最大子矩阵

时间限制: 1 Sec  内存限制: 32 MB
提交: 168  解决: 65
[提交][状态][讨论版][命题人:外部导入]

题目描述

已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是1 * 1)子矩阵。
比如,如下4 * 4的矩阵

0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2

的最大子矩阵是

9 2
-4 1
-1 8

这个子矩阵的大小是15。

输入

输入是一个N * N的矩阵。输入的第一行给出N (0 < N <= 100)。
再后面的若干行中,依次(首先从左到右给出第一行的N个整数,再从左到右给出第二行的N个整数……)给出矩阵中的N2个整数,整数之间由空白字符分隔(空格或者空行)。
已知矩阵中整数的范围都在[-127, 127]。

输出

测试数据可能有多组,对于每组测试数据,输出最大子矩阵的大小。

样例输入

1
27 
3
-40 29 -16 
38 18 22 
24 -35 5 

样例输出

27
78

本题为二维的最大连续子序列和,实际可以降至一维进行求解,对于确定的从第 i 列到 第 j 列,将同一行的数相加,最终得到一个一维的数序列,对于这个数序列求最大连续子序列和就可以啦。

最大连续子序列主要内容:

  1. dp[i]表示以a[i]作为末尾的连续序列的最大和
  2. 状态转移方程:dp[i]=max{ a[i],dp[i-1]+a[i]}

!注意看注释

#include
#include
using namespace std;
int main() {
	int N;
	while (cin >> N) {
		int a[110][110] = { 0 }, ans = -1e9;
		for (int i = 1; i <= N; i++) {
			for (int j = 1; j <= N; j++) {
				cin >> a[i][j];//a[i][j]存放原矩阵第i行前j列的和
				a[i][j] += a[i][j - 1];
			}
		}
		//枚举前k行,第i+1列至第j列(i,j]的和,得出最大值ans
		for (int i = 0; i < N; i++) {//i控制子矩阵的最左边 
			for (int j = i + 1; j <= N; j++) {//j控制子矩阵的最右边 
				int subsum = 0;
				for (int k = 1; k <= N; k++) {//k控制子矩阵的最下边,即遍历行号 
					if (subsum < 0) subsum = 0;
					subsum += a[k][j] - a[k][i];
					ans = max(subsum, ans);
				}
			}
		}
		cout << ans << endl;
	}
	return 0;
}

 

你可能感兴趣的:(ACM)