bzoj3791: 作业
3791: 作业
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3791
Time Limit: 10 Sec Memory Limit: 256 MBDescription
众所周知,白神是具有神奇的能力的。
比如说,他对数学作业说一声“数”,数学作业就会出于畏惧而自己完成;对语文作业说一声“语”,语文作业就会出于畏惧而自己完成。
今天,语文老师和数学老师布置了许多作业,同学们纷纷寻找白神寻求帮助。白神作为一个助人为乐的人,便答应下来。
回到家,白神将这N份作业按顺序摊开,发现语文作业数学作业混在一起,这就让白神苦恼起来,他如果对连续一段作业喊出“数”,那么里面的语文作业就会由于过于慌乱而写满错解,不过如果白神再对其喊一声“语”,它又会写满正确答案。
虽然白神很强大,但是能力还是有限制的,一天只能使用K次,现在,白神想知道他能正确的完成多少份作业。
Input
第一行两个整数N,K。
第二行N个0或者1表示这份作业是语文作业还是数学作业。
Output
输出一个整数,表示白神能正确完成的作业数。
Sample Input
5 2
0 1 0 1 0
0 1 0 1 0
Sample Output
4
HINT
100%的数据中N ≤ 100000,K<=50.
题解:dp, 相当于
给一个长度为 N 的序列,序列中每个元素初始为无色,每个元素有一个目标颜色(黑或白),你有 K 次机会选择一个区间染色,注意颜色会覆盖。问最多能让多少个元素满足目标颜色。
注意染到最后一定是黑白相间的。而最多形成 2*k-1 个黑白相间的段,并且个数小于 2*k-1 的黑白相间的段都能被染出。
dp[i][j][0/1] 表示染到第 i 个,已经有了 j 段,最后一段是 白/黑色,最多的满足目标颜色的元素个数。
#include <bits/stdc++.h> #define ll long long using namespace std; const int M = 100005; int dp[M][105][2], a[M]; int main() { int n, k, ans = 0; scanf("%d%d", &n, &k); int tot = k * 2 - 1; for(int i = 1; i <= n; i++)scanf("%d", &a[i]); for(int i = 1; i <= n; i++) for(int j = 1; j <= tot; j++){ dp[i][j][0] = max(dp[i - 1][j][0], dp[i - 1][j - 1][1]); dp[i][j][1] = max(dp[i - 1][j][1], dp[i - 1][j - 1][0]); if(a[i])dp[i][j][1]++; else dp[i][j][0]++; } /*for(int i = 1; i <= tot; i++) ans = max(dp[n][i][0], max(ans, dp[n][i][1]));*/ printf("%d", max(dp[n][tot][1], dp[n][tot][0])); return 0; }