Description
有n道题目,有两个人分别会做某些题目,有p次偷看机会,每次可以偷看某个人最多连续k道题目,求最多偷看几道题目。(注意:是可以重叠的)
Sample Input
6 2 3
3 1 3 6
4 1 2 5 6
Sample Output
4
你设f[i][j][x][y]为到第i道题目,已看了j次,对第一个人还剩x次机会,对第二个人还剩y次机会。
反三种情况转移即可。
有一个优化,如果
p
>
=
2
∗
(
n
+
K
−
1
)
/
K
p >= 2 * (n + K - 1) / K
p>=2∗(n+K−1)/K你就直接算。
唉,状态有点繁琐,真是烦死我了。。。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
int _min(int x, int y) {return x < y ? x : y;}
int _max(int x, int y) {return x > y ? x : y;}
int read() {
int s = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
return s * f;
}
int a[1100], b[1100];
int f[2][1010][51][51];
int s1[1100], s2[1100];
int main() {
int n = read(), p = read(), K = read();
int h1 = read(); for(int i = 1; i <= h1; i++) a[i] = read(), s1[a[i]] = 1;
int h2 = read(); for(int i = 1; i <= h2; i++) b[i] = read(), s2[b[i]] = 1;
int ans = 0;
if(p >= 2 * (n + K - 1) / K) {
for(int i = 1; i <= n; i++) if(s1[i] || s2[i]) ans++;
printf("%d\n", ans);
return 0;
}
int now = 0; memset(f[now], -1, sizeof(f[now]));
f[now][0][0][0] = 0;
for(int i = 1; i <= n; i++) {
now ^= 1; memset(f[now], -1, sizeof(f[now]));
for(int j = 0; j <= p; j++) {
for(int x = 0; x <= K; x++) {
for(int y = 0; y <= K; y++) {
if(j <= p - 2) {
f[now][j + 2][K - 1][K - 1] = _max(f[now][j + 2][K - 1][K - 1], _max(f[now ^ 1][j][x][y], 0) + (s1[i] | s2[i])),
ans = _max(ans, f[now][j + 2][K - 1][K - 1]);
}
if(j <= p - 1) {
if(y && f[now ^ 1][j][x][y] != -1) f[now][j + 1][K - 1][y - 1] = _max(f[now][j + 1][K - 1][y - 1], _max(f[now ^ 1][j][x][y], 0) + (s1[i] | s2[i])),
ans = _max(ans, f[now][j + 1][K - 1][y - 1]);
else f[now][j + 1][K - 1][0] = _max(f[now][j + 1][K - 1][0], _max(f[now ^ 1][j][x][0], 0) + s1[i]),
ans = _max(ans, f[now][j + 1][K - 1][0]);
if(x && f[now ^ 1][j][x][y] != -1) f[now][j + 1][x - 1][K - 1] = _max(f[now][j + 1][x - 1][K - 1], _max(f[now ^ 1][j][x][y], 0) + (s1[i] | s2[i])),
ans = _max(ans, f[now][j + 1][x - 1][K - 1]);
else f[now][j + 1][0][K - 1] = _max(f[now][j + 1][0][K - 1], _max(f[now ^ 1][j][0][y], 0) + s2[i]),
ans = _max(ans, f[now][j + 1][0][K - 1]);
} int hh = 0;
if(f[now ^ 1][j][x][y] != -1) {
if(x) hh |= s1[i]; if(y) hh |= s2[i];
f[now][j][_max(0, x - 1)][_max(0, y - 1)] = _max(f[now][j][_max(0, x - 1)][_max(0, y - 1)], f[now ^ 1][j][x][y] + hh);
ans = _max(ans, f[now][j][_max(0, x - 1)][_max(0, y - 1)]);
}
}
}
}
} printf("%d\n", ans);
return 0;
}