最大和(动态规划)

最大和

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 5
描述

给定一个由整数组成二维矩阵(r*c),现在需要找出它的一个子矩阵,使得这个子矩阵内的所有元素之和最大,并把这个子矩阵称为最大子矩阵。 
例子:
0 -2 -7 0 
9 2 -6 2 
-4 1 -4 1 
-1 8 0 -2 
其最大子矩阵为:

9 2 
-4 1 
-1 8 
其元素总和为15。 

输入
第一行输入一个整数n(0<n<=100),表示有n组测试数据;
每组测试数据:
第一行有两个的整数r,c(0<r,c<=100),r、c分别代表矩阵的行和列;
随后有r行,每行有c个整数;
输出
输出矩阵的最大子矩阵的元素之和。
样例输入
1
4 4
0 -2 -7 0 
9 2 -6 2 
-4 1 -4 1 
-1 8 0 -2 
样例输出
15


最大和,和最大区间数相似,不过由一维变成了二维

那么sum这个数组的作用依旧能用上,sum可以方便运算

若用sum求每一列的累加和的话

那么需要想办法解决是哪个行的问题,,分析可知,这个不能用一层for循环解决了,只能暴力

sum[i][j]表示mp[1][j]到mp[i][j]的累加和 (某一列的值)

而sum[i][j]- sum[p][j]为j列从p+1到i行的值

两层for循环表从i到j行,暴力枚举子矩阵,而一层for循环列举从1列到m列的i-j行的最大值

#include <bits/stdc++.h>
using namespace std;

const int MAX = 101;

int sum[MAX][MAX];
int mp[MAX][MAX];

int main()
{
	int t;
	scanf("%d", &t);
	while(t--)
	{
		int n, m;
		scanf("%d %d\n", &n, &m);
		memset(sum,0,sizeof(sum));
		memset(mp, 0, sizeof(mp));
		for(int i = 1; i <= n; i++)
		{
			for(int j = 1; j <= m; j++)
			{
				scanf("%d",&mp[i][j]);
				sum[i][j] = sum[i-1][j] + mp[i][j];
			}
		}
		
		int res_n = INT_MIN;
		for(int i = 1; i <= n; i++)
		{
			for(int j = i; j <= n; j++)
			{
				int max_n = 0;
				for(int k = 1; k <= m; k++)
				{
					if(max_n <= 0)
					{
						max_n = sum[j][k] -  sum[i-1][k];
					}
					else
					{
						max_n = max_n + sum[j][k] - sum[i-1][k];
					}
					res_n = max(max_n, res_n);
				}
			}
		}
		printf("%d\n", res_n);
	}
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/yinghui_yht/article/details/79676756