题目

源地址:

http://poj.org/problem?id=1050

理解

题意不难理解,在一个矩阵中寻找一个和最大的子矩阵,可以看作是一个二维的DP问题。不过受到时间的限制,太过暴力的程序显然是不行的,所以现在的问题在于,如何把一个二维的问题转化为一个一维的问题。小脑一动,我们可以想到可以将把矩阵的高度压缩为1之后,在进行一次简单的求最大子序列和就可以实现了。

代码


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <stack>
#include <queue>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <sstream>
#include <fstream>
#define debug puts("-----")
#define pi (acos(-1.0))
#define eps (1e-8)
#define inf (1<<28)
using namespace std;

//#define LOCAL
#define MAXN 102

int n, a[MAXN][MAXN];
int tmp[MAXN];
int maxALL, maxONE;

void init()
{
    scanf("%d", &n);
    memset(tmp, 0, sizeof(tmp));
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            scanf("%d", &a[i][j]);
        }
    }
}

int dp(int *arr, int n)
{
    int max = 0, x = 0;
    for (int i = 0; i < n; i++)
    {
        if (x < 0) x = arr[i];
        else
        {
            x += arr[i];
            if (x > max)   max = x;
        }
    }
    return max;
}

int main(int argc, char const *argv[])
{
#ifdef LOCAL
    freopen("1050.in", "r", stdin);
    //freopen(".out", "w", stdout);
#endif
    init();
    for (int i = 0; i < n; i++)
    {
        memset(tmp, 0, sizeof(tmp));
        for (int j = i; j < n; j++)
        {
            for (int k = 0; k < n; k++)    tmp[k] += a[j][k];
            maxONE = dp(tmp, n);
            if (maxONE > maxALL)   maxALL = maxONE;
        }
    }
    cout << maxALL << endl;
    return 0;
}

更新日志

  • 2014年10月07日 已AC,因为freopen忘了改WA了一发。