codeforces 467-C. George and Job(前缀和+dp)

来源:互联网 发布:观察者模式js 编辑:程序博客网 时间:2024/06/05 10:45

The new ITone 6 has been released recently and George got really keen to buy it. Unfortunately, he didn’t have enough money, so George was going to work as a programmer. Now he faced the following problem at the work.

Given a sequence of n integers p1, p2, …, pn. You are to choose k pairs of integers:

[l1, r1], [l2, r2], …, [lk, rk] (1 ≤ l1 ≤ r1 < l2 ≤ r2 < … < lk ≤ rk ≤ n; ri - li + 1 = m), 

in such a way that the value of sum这里写图片描述 is maximal possible. Help George to cope with the task.
Input

The first line contains three integers n, m and k (1 ≤ (m × k) ≤ n ≤ 5000). The second line contains n integers p1, p2, …, pn (0 ≤ pi ≤ 109).
Output

Print an integer in a single line — the maximum possible value of sum.
Examples
Input

5 2 1
1 2 3 4 5

Output

9

Input

7 1 3
2 10 7 18 5 33 0

Output

61

题目大意:
给出n个数,找出k段长度为m的不相交的区间,使这些区间的和最大。

解题思路:

状态表示:

dp[i][j]表示前i个数找出j段长度为m的最大区间和。

状态转移方程:

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

其中sum[i]表示前i个数的和。

#include<iostream>#include<cstdio>#include<cstring>using namespace std;#define maxn 5005typedef long long LL;LL s[maxn],sum[maxn],dp[maxn][maxn];int main(){    LL n,m,k;    while(~scanf("%lld%lld%lld",&n,&m,&k))    {        memset(sum,0,sizeof(sum));        memset(dp,0,sizeof(dp));        for(int i=1;i<=n;i++)        {            scanf("%lld",&s[i]);            sum[i]=sum[i-1]+s[i];        }        for(int i=1;i<=n;i++)          for(int j=1;j<=k;j++)            dp[i][j]=i>=m?max(dp[i-1][j],dp[i-m][j-1]+sum[i]-sum[i-m]):dp[i-1][j];        printf("%lld\n",dp[n][k]);    }    return 0;}
原创粉丝点击