「BZOJ3791」作业
题解:
比正解的做法要复杂
正解直接确定了最多有2k-1段
并且可以证明2k-1是一定可以覆盖的
于是可以直接dp
我的想法是先覆盖一段黑的,然后白的覆盖上去
所以f[i][0/1/2][0/1/2]
表示当前下面那层颜色是啥,上面那层颜色是啥
代码:
#include <bits/stdc++.h> using namespace std; #define rint register int #define IL inline #define rep(i,h,t) for (rint i=h;i<=t;i++) #define dep(i,t,h) for (rint i=t;i>=h;i--) const int N=1e5+10; int n,kk,a[N]; int f[N][51][3][3]; const int INF=1e9; IL int max(rint x,rint y) { return x>y?x:y; } int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); ios::sync_with_stdio(false); cin>>n>>kk; rep(i,1,n) cin>>a[i]; rep(k,0,50) { rep(i,0,2) rep(j,0,2) f[0][k][i][j]=-INF; f[0][k][0][0]=0; } rep(i,1,n) rep(k,0,kk) { int (*f1) [3]=f[i][k],(*f2) [3]=f[i-1][k],(*f4) [3]; if (k) f4=f[i][k-1]; int ans1=0,ans2=0,ans3=0,ans4=0,ans5=0; rep(k1,0,2) rep(k2,0,2) ans1=max(ans1,f2[k1][k2]); f1[0][0]=ans1; ans2=max(f2[1][0],f2[1][2]); if (k) ans2=max(ans2,f4[0][0]); if (a[i]==0) ans2++; f1[1][0]=ans2; ans3=max(f2[2][0],f2[2][1]); if (k) ans3=max(ans3,f4[0][0]); if (a[i]==1) ans3++; f1[2][0]=ans3; ans4=f2[2][1]; if (k) ans4=max(ans4,f4[2][0]); if (a[i]==0) ans4++; f1[2][1]=ans4; ans5=f2[1][2]; if (k) ans5=max(ans5,f4[1][0]); if (a[i]==1) ans5++; f1[1][2]=ans5; } int ans=0; rep(i,0,2) rep(j,0,2) ans=max(ans,f[n][kk][i][j]); cout<<ans<<endl; return 0; }