codeforces-467C-George and Job【dp】

codeforces-467C-George and Job【dp】

                time limit per test1 second     memory limit per test256 megabytes

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.

input
5 2 1
1 2 3 4 5
output
9

input
7 1 3
2 10 7 18 5 33 0
output
61

题目链接:cf-467C

题目大意:有一个长度为n的序列,问取k个组合,每个组合长度为m,所能取到的最大值。每个数字只能取一次

题目思路:dp[i][j]第一个参数表示到第i个数字,第二个参数表示有j个组合,dp的值表示当前能去到的最大值。

状态转移方程为:

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

两种可能性,当前的i这个值,取或者不取。

以下是代码:

#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <string>
#include <cstring>
using namespace std;
long long p[6000];
long long dp[5001][5001];
long long ret[6000]; 
int main(){
    long long n,m,k;
    cin >> n >> k >> m;
    for (int i = 0; i < n; i++)  cin >> p[i];
    ret[0] = p[0]; 
    for (int i = 1; i < n; i++)
    {
        ret[i] = ret[i - 1] + p[i];
        if (i >= k) ret[i] -= p[i - k];
    }
    dp[0][0] = 0;
    dp[k-1][1] = ret[k-1];
    for (int i = k; i < n; i++)
    {
        for (int j = 0; j <= m; j++)
        {
            if (j == 0) dp[i][j] = dp[i-1][j];
            else    dp[i][j] = max(dp[i-k][j-1] + ret[i],dp[i-1][j]);
        }
    }
    cout << dp[n-1][m] << endl; 
    return 0;
}

你可能感兴趣的:(467C)