選元素(線性DP)
阿新 • • 發佈:2022-05-17
題意
給定一個長度為 \(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; }