HDU 1081 To The Max 动态规划

来源:互联网 发布:linux 父目录 编辑:程序博客网 时间:2024/06/05 10:31

题目大意:

就是现在给出一个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;}


0 0
原创粉丝点击