动态规划最大子矩阵
1768:最大子矩阵
总Time Limit:
1000ms
Memory Limit:
65536kB
Description
已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是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。
Input
输入是一个N * N的矩阵。输入的第一行给出N (0 < N <= 100)。再后面的若干行中,依次(首先从左到右给出第一行的N个整数,再从左到右给出第二行的N个整数……)给出矩阵中的N2个整数,整数之间由空白字符分隔(空格或者空行)。已知矩阵中整数的范围都在[-127, 127]。
Output
输出最大子矩阵的大小。
Sample Input
4
0 -2 -7 0 9 2 -6 2
-4 1 -4 1 -1
8 0 -2
Sample Output
15
直接暴力枚举所有的组合
方法类似最长上升子序列
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAX(a,b) (a>b?a:b)
#define MIN(a,b) (a<b?a:b)
const int LEN = 100 + 4;
const int INF = -(1 << 31);
int ar[LEN][LEN];
int f[LEN];
int main(void)
{
int N;
cin >> N;
for (int i = 1; i <= N; ++i)
for (int j = 1; j <= N; ++j)
scanf("%d", &ar[i][j]);
int num = INF;//num用来储存从1到n的最大子矩阵的和的最大值
for (int i = 1; i <= N; ++i)
{
memset(f, 0, sizeof(f));
for (int j = i; j <= N; ++j)
{
for (int k = 1; k <= N; ++k)
f[k] += ar[j][k];//用来记录以i行开始的每一列的总和
int maxn = f[0],ans = f[0];/*maxn用来储存从i到j的以k为结尾的最大子矩阵,ans用来储存从i到n的最大子矩阵*/
for (int k = 1; k <= N; ++k)
{
if (maxn < 0)
maxn = f[k];
else
maxn += f[k];
ans = MAX(ans, maxn);
}
num = MAX(ans, num);
}
}
cout << num << endl;
return 0;
}