给定一个长度为 n 的整数序列 a1,a2,…,an。
请你从中挑选 x 个元素,要求:
原序列中的每一个长度为 k 的连续子序列都至少包含一个被选中的元素。
满足条件 1 的前提下,所选 x 个元素的相加之和应尽可能大。
输出最大可能和。
输入格式
第一行包含三个整数 n,k,x。
第二行包含 n 个整数 a1,a2,…,an。
输出格式
如果无法满足题目要求,则输出 −1。
否则,输出一个整数,表示所选元素的最大可能和。
数据范围
前三个测试点满足 1≤k,x≤n≤6。
所有测试点满足 1≤k,x≤n≤200,1≤ai≤109。
输入样例1:
5 2 3
5 1 3 10 1
输出样例1:
18
输入样例2:
6 1 5
10 30 30 70 10 10
输出样例2:
-1
输入样例3:
4 3 1
1 100 1 1
输出样例3:
100
题意:
给你n个数,选k个数,让你从原序列中的每一个长度为 k 的连续子序列都至少包含一个被选中的元素,要求和值最大。
题解:
首先选数的范围是n的n次方级别,那么只能考虑用dp和贪心的方法来写;
题目有顺序关系,一般来说都是序列型dp
#include<bits/stdc++.h>
using namespace std;
const int N = 310;
ll f[N][N];
int a[N];
typedef long long ll;
/*
序列dp第一维遍历i个物品第二维度遍历条件
f[i][j]从前i个物品选j个物品的最大价值
f[i][j]=max(f[i-k+1][j-1]+a[i],f[i][j]);
*/
int main() {
int n, k, m;
cin >> n >> k >> m;
for (int i = 1; i <= n; i++)cin >> a[i];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
for (int l = max(0, i - k); l < i; l++) {
f[i][j] = max(f[i][j], f[i - 1][j - 1] + a[i]);
}
}
}
ll res = -1;
/*for (int i = 1; i <= n; i++) {
res = max(res, f[i][m]);
}*/
//注意一下边界条件只有从第n-k+1的地方开始才能保证正确的连续的k个子序列都有一个数
//而不是1
for (int i = n - k + 1; i <= n; i++) {
res = max(res, f[i][m]);
}
printf("%lld", res);
return 0;
}