HDU 1081 To The Max 动态规划

题目大意:

就是现在给出一个n*n的矩阵中的所有的值,求其中取出一块区域的最大和。


大致思路:

首先考虑一维上的相似的一个问题:

对于数列a[ n ]找出连续的子串使得和最大,那么用 dp[ i ] 表示以第 i 个作为结尾的字串最大和, 那么 dp[ i ] = max(dp[ i - 1 ] + a[ i ], a[ i ])

那么一个二维的情况,我们讨论以第 i 行到第 j 行的情况,将其作为一个整体,预处理每列的前n行的和就可以很快地得到每列第 i  行到第 j 行的和,作为一个整体就类似于上面以为的步骤了,预处理复杂度为O(n*n),枚举 i 和 j ,dp算对应情形下的最大子列和,时间复杂度为O(n^3)

总体时间复杂度为O(n^3)可以接受


代码如下:

Result  :  Accepted     Memory  :  376 KB     Time  :  0 ms

/*
 * Author: Gatevin
 * Created Time:  2014/8/15 17:13:49
 * File Name: haha.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;

int n;
int a[101][101];
int sum[101][101];
int dp[101][101];
int main()
{
    while(~scanf("%d", &n))
    {
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                scanf("%d", &a[i][j]);
        memset(sum, 0, sizeof(sum));
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                sum[i][j] = sum[i][j - 1] + a[i][j];
        memset(dp, 0, sizeof(dp));
        for(int i = 1; i <= n; i++)
        {
            for(int j = i; j <= n; j++)
            {
                int tmp = 0;
                for(int k = 1; k <= n; k++)
                {
                    tmp += sum[k][j] - sum[k][i - 1];
                    dp[i][j] = max(dp[i][j], tmp);
                    if(tmp < 0) tmp = 0;
                }
            }
        }
        int answer = dp[1][1];
        for(int i = 1; i <= n; i++)
        {
            for(int j = i; j <= n; j++)
            {
                answer = max(answer, dp[i][j]);
            }
        }
        printf("%d\n", answer);
    }
    return 0;
}


你可能感兴趣的:(TO,动态规划,max,HDU,the,1081)