选元素(线性DP)

题意

给定一个长度为 \(n\) 的整数序列 \(a_1, a_2, \dots, a_n\)

请你从中挑选 \(x\) 个元素,要求:

  • 原序列中的每一个长度为 \(k\) 的连续子序列都至少包含一个被选中的元素。

输出最大可能和。

数据范围

\(1 \leq n, k, x \leq 200\)

思路

考虑使用DP。令\(f_{i, j}\)表示最后一个选取的元素的下标是\(i\),总共选取了\(j\)个元素的最大和。则:

\(f_{i, j} = \max\limits_{i - k \leq t < i}(f_{i, j}, f_{t, j - 1})\)

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long ll;

const int N = 210;

int n, kk, x;
ll a[N];
ll f[N][N];

int main()
{
    scanf("%d%d%d", &n, &kk, &x);
    for(int i = 1; i <= n; i ++) scanf("%lld", &a[i]);
    memset(f, -0x3f, sizeof f);
    f[0][0] = 0;
    for(int i = 1; i <= n; i ++) {
        for(int j = 1; j <= x; j ++) {
            for(int k = max(0, i - kk); k < i; k ++) {
                f[i][j] = max(f[i][j], f[k][j - 1] + a[i]);
            }
        }
    }
    ll ans = -1;
    for(int i = n - kk + 1; i <= n; i ++) ans = max(f[i][x], ans);
    printf("%lld\n", ans);
    return 0;
}
posted @ 2022-05-17 19:46  pbc的成长之路  阅读(25)  评论(0)    收藏  举报