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;
}