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;
}