问题 E: 最大子矩阵
时间限制: 1 Sec 内存限制: 32 MB
提交: 61 解决: 25
[提交][状态][讨论版][命题人:外部导入]
题目描述
已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是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
#include<iostream>
#include<algorithm>
using namespace std;
//最大连续子序列和的二维问题,动态规划解决
//因为每一行的最大子矩阵不确定由哪几列构成,dp二维数组写法不需要且不可行
int main() {
int N;
while (cin >> N) {
int sum[110][110] = { 0 }, ans = -1e9;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
cin >> sum[i][j];//sum[i][j]存放原矩阵第i行前j列的和
sum[i][j] += sum[i][j - 1];//即转化为对应的1维情况,对每一列处理
}
}
//枚举前k行,第i+1列至第j列(i,j]的和,得出最大值ans
for (int i = 0; i <= N; i++) {
for (int j = i + 1; j <= N; j++) {
int subsum = 0;
for (int k = 1; k <= N; k++) {
// 动态规划思想,subSum<0将会减少总和,所以此时将其置0
if (subsum < 0) subsum = 0;
subsum += sum[k][j] - sum[k][i];
ans = max(ans, subsum);
}
}
}
cout << ans << endl;
}
return 0;
}
#include<iostream>
#include<algorithm>
using namespace std;
//尝试了一下使用dp二维数组,不需要且不可行
//因为每一行的最大子矩阵不确定由哪几列构成
int main() {
int N;
while (cin >> N) {
int a[110][110] = { 0 }, ans = 1e-9;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
cin >> a[i][j];
a[i][j] += a[i][j - 1];
}
}
for (int i = 0; i < N; i++) {
for (int j = i + 1; j <= N; j++) {
int subsum = 0;
for (int k = 1; k <= N; k++) {
if (subsum < 0) subsum = 0;
subsum += a[k][j] - a[k][i];
ans = max(subsum, ans);
}
}
}
cout << ans << endl;
}
return 0;
}