Codeforces Round #267 Div2 C George and Job --DP

题意:把长度为n的序列分成k个m长的连续小序列,这些连续小序列的和最大是多少。

解法:显然DP。

定义: dp[i][j] 为前 i 个元素分成j个m端,且 i 是第j个的末尾的最大和。

那么有: dp[i][j] = max(dp[i-1][j], dp[i-m][j-1]+sum[i]-sum[i-m])

5000*5000的空间,是有点大。。

代码:

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cstdlib>

#include <cmath>

#include <algorithm>

#define lll __int64

using namespace std;



lll dp[5002][5001];

lll a[5002],sum[5003];



int main()

{

    int n,m,k;

    int i,j;

    while(scanf("%d%d%d",&n,&m,&k)!=EOF)

    {

        sum[0] = 0;

        for(i=1;i<=n;i++)

        {

            scanf("%I64d",&a[i]);

            sum[i] = sum[i-1]+a[i];

        }

        for(i=0;i<=n;i++)

            for(j=0;j<=k;j++)

                dp[i][j] = 0;

        for(i=m;i<=n;i++)

        {

            dp[i][0] = max(dp[i][0],dp[i-1][0]);

            for(j=1;j<=k;j++)

            {

                dp[i][j] = max(dp[i][j],dp[i-1][j]);

                dp[i][j] = max(dp[i][j],dp[i-m][j-1]+sum[i]-sum[i-m]);

            }

        }

        cout<<dp[n][k]<<endl;

    }

    return 0;

}
View Code

 

你可能感兴趣的:(codeforces)