题目描述
已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是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
思路:用sum[i][j]表示前i行第j列的子矩阵和。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 110;
int N;
int sum[maxn][maxn];
void DP() {
int temp = 0;
int ans = sum[1][1];
for (int i = 0; i <= N - 1; i++) { // i要从0开始
for (int j = i + 1; j <= N; j++) {
temp = 0;
for (int t = 1; t <= N; t++) {
// sum[j][t] - sum[i][t]表示第i+1到第j行第t列的子矩阵和
temp = max(temp + sum[j][t] - sum[i][t], sum[j][t] - sum[i][t]);
if (temp > ans) ans = temp;
}
}
}
printf("%d\n", ans);
}
int main() {
int k;
while (scanf("%d", &N) != EOF) {
memset(sum, 0, sizeof(sum));
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
scanf("%d", &k);
sum[i][j] = sum[i - 1][j] + k; // sum[i][j]表示前i行第j列的子矩阵和
}
}
DP();
}
return 0;
}