作业(homework)
题目背景:
众所周知,白神是具有神奇的能力的。
比如说,他对数学作业说一声“数”,数学作业就会出于畏惧而自己完成;对语文作业说一声“语”,语文作业就会出于畏惧而自己完成。
今天,语文老师和数学老师布置了许多作业,同学们纷纷寻找白神寻求帮助。白神作为一个助人为乐的人,便答应下来。
回到家,白神将这N份作业按顺序摊开,发现语文作业数学作业混在一起,这就让白神苦恼起来,他如果对连续一段作业喊出“数”,那么里面的语文作业就会由于过于慌乱而写满错解,不过如果白神再对其喊一声“语”,它又会写满正确答案。
虽然白神很强大,但是能力还是有限制的,一天只能使用K次,现在,白神想知道他能正确的完成多少份作业。
输入格式:
第一行两个整数N,K。
第二行N个0或者1表示这份作业是语文作业还是数学作业。
输出格式:
输出一个整数,表示白神能正确完成的作业数。
Input
5 2
0 10 1 0
Output
4
数据规模:
30%的数据中N ≤ 30,K<=10;
80%的数据中N ≤ 1000,K<=10;
100%的数据中N ≤ 100000,K<=50.
贪心:1个点最多刷2遍,第一次最好全刷(刷一段能行的全刷也行)
于是得出接下来肯定是一段一段刷(不相交)
然后Dp/
注意可能不只k-1部分
0..0 1..1 0..0 1..1 0..0 / 第一次刷0
这样的话可能有最后多出来的0部分
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<functional> #include<cmath> #include<cctype> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Rep(i,n) for(int i=0;i<n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define ForD(i,n) for(int i=n;i;i--) #define Forp(x) for(int p=pre[x];p;p=next[p]) #define RepD(i,n) for(int i=n;i>=0;i--) #define MAXN (100000+10) #define MAXK (50+10) int n,k,a[MAXN],ans=0; int f[MAXN][MAXK][2]; //到n取k 0:未取 1:续取 void dp() { memset(f,0,sizeof(f)); For(i,n) { Rep(j,k+1) { f[i][j][0]=max(f[i-1][j][0],(!j)?0:f[i-1][j-1][1])+(a[i]==0); f[i][j][1]=max(f[i-1][j][1],f[i-1][j][0])+(a[i]==1); } f[i][k+1][0]=max(f[i-1][k+1][0],f[i-1][k][1])+(a[i]==0); } // ans=max(max(f[n][k][0],f[n][k][1]),ans); Rep(j,k+1) ans=max(max(f[n][j][0],f[n][j][1]),ans); ans=max(f[n][k+1][0],ans); } int main() { freopen("homework.in","r",stdin); freopen("homework.out","w",stdout); scanf("%d%d",&n,&k);k-=2; For(i,n) scanf("%d",&a[i]); dp(); // cout<<ans<<endl; For(i,n) a[i]^=1; dp(); cout<<ans<<endl; return 0; }