最大和
时间限制:
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; }