「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;
}

 

posted @ 2018-09-02 22:21  尹吴潇  阅读(143)  评论(0编辑  收藏  举报