zoukankan      html  css  js  c++  java
  • BZOJ2706 : [SDOI2012]棋盘覆盖

    A类数据:

    将棋盘黑白染色,相邻的点之间连边,求出二分图最大匹配即可。

    B类数据:

    答案为$lfloorfrac{n^2-1}{3} floor$,用FFT加速计算即可,时间复杂度$O(Llog L)$。

    C类数据:

    轮廓线DP,对于轮廓线上每个格子,要么为空,要么被占据,要么被占据且还要向下延伸一格。

    设$f[i][j][S][k]$表示考虑到$(i,j)$,轮廓线上$m$个格子状态为$S$,转角处被占据状态为$k$时最多能放几个俄罗斯方块。

    时间复杂度$O(nm3^m)$。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    char sn[200010],sm[200010],type[5];int K;
    namespace SubA{
    const int N=105,M=N*N,inf=~0U>>2;
    int n,m,cnt,i,j,a[N][N],id[N][N],S,T,h[M],gap[M],ans;
    struct E{int t,f;E*nxt,*pair;}*g[M],*d[M],pool[M*6],*cur=pool;
    inline void add(int s,int t){
      if(!s||!t)return;
      E*p=cur++;p->t=t;p->f=1;p->nxt=g[s];g[s]=p;
      p=cur++;p->t=s;p->f=0;p->nxt=g[t];g[t]=p;
      g[s]->pair=g[t];g[t]->pair=g[s];
    }
    int sap(int v,int flow){
      if(v==T)return flow;
      int rec=0;
      for(E*p=d[v];p;p=p->nxt)if(h[v]==h[p->t]+1&&p->f){
        int ret=sap(p->t,min(flow-rec,p->f));
        p->f-=ret;p->pair->f+=ret;d[v]=p;
        if((rec+=ret)==flow)return flow;
      }
      if(!(--gap[h[v]]))h[S]=T;
      gap[++h[v]]++;d[v]=g[v];
      return rec;
    }
    void solve(){
      sscanf(sn,"%d",&n);
      sscanf(sm,"%d",&m);
      while(K--)scanf("%d%d",&i,&j),a[i][j]=1;
      for(i=1;i<=n;i++)for(j=1;j<=m;j++)if(!a[i][j])id[i][j]=++cnt;
      S=cnt+1;T=S+1;
      for(i=1;i<=n;i++)for(j=1;j<=m;j++)if((i+j)&1)add(S,id[i][j]);else add(id[i][j],T);
      for(i=1;i<=n;i++)for(j=1;j<=m;j++)if((i+j)&1){
        add(id[i][j],id[i][j-1]);
        add(id[i][j],id[i][j+1]);
        add(id[i][j],id[i-1][j]);
        add(id[i][j],id[i+1][j]);
      }
      for(gap[0]=T,i=1;i<=T;i++)d[i]=g[i];
      while(h[S]<T)ans+=sap(S,inf);
      printf("%d",ans);
    }
    }
    namespace SubB{
    const int N=262150;
    const double pi=acos(-1.0);
    struct comp{
      double r,i;comp(double _r=0,double _i=0){r=_r,i=_i;}
      comp operator+(const comp&x){return comp(r+x.r,i+x.i);}
      comp operator-(const comp&x){return comp(r-x.r,i-x.i);}
      comp operator*(const comp&x){return comp(r*x.r-i*x.i,r*x.i+i*x.r);}
      comp conj(){return comp(r,-i);}
    }A[N],B[N];
    int n,i,j,k,pos[N],c[N];
    void FFT(comp*a,int n,int t){
      for(int i=1;i<n;i++)if(i<pos[i])swap(a[i],a[pos[i]]);
      for(int d=0;(1<<d)<n;d++){
        int m=1<<d,m2=m<<1;double o=pi*2/m2*t;comp _w(cos(o),sin(o));
        for(int i=0;i<n;i+=m2){
          comp w(1,0);
          for(int j=0;j<m;j++){
            comp&A=a[i+j+m],&B=a[i+j],t=w*A;
            A=B-t;B=B+t;w=w*_w;
          }
        }
      }
      if(t==-1)for(int i=0;i<n;i++)a[i].r/=n;
    }
    void solve(){
      n=strlen(sn);
      for(i=0;i<n;i++)A[i]=comp(sn[n-i-1]-'0',sn[n-i-1]-'0');
      for(k=1;k<n+n;k<<=1);
      j=__builtin_ctz(k)-1;
      for(i=0;i<k;i++)pos[i]=pos[i>>1]>>1|((i&1)<<j);
      FFT(A,k,1);
      for(i=0;i<k;i++){
        j=(k-i)&(k-1);
        B[i]=(A[i]*A[i]-(A[j]*A[j]).conj())*comp(0,-0.25);
      }
      FFT(B,k,-1);
      for(i=0;i<k;i++)c[i]=int(B[i].r+0.5);
      for(i=0;i<k;i++)c[i+1]+=c[i]/10,c[i]%=10;
      for(n=k;!c[n];n--);
      c[0]--;
      for(i=n;~i;i--){
        if(i)c[i-1]+=c[i]%3*10;
        c[i]/=3;
      }
      while(n&&!c[n])n--;
      for(i=n;~i;i--)printf("%d",c[i]);
    }
    }
    namespace SubC{
    const int N=11,M=180000;
    int n,m,i,j,k,t,S,x,E,a[N][N],cnt,q[M],h[1<<22],f[M][2],g[M][2],ans;
    inline int get(int x,int y){return x>>(y+y)&3;}
    inline void clr(){for(int i=1;i<=cnt;i++)f[i][0]=f[i][1]=-1;}
    inline void nxt(){for(int i=1;i<=cnt;i++)g[i][0]=f[i][0],g[i][1]=f[i][1];}
    inline void up(int&x,int y){if(x<y)x=y;}
    void solve(){
      sscanf(sn,"%d",&n);
      sscanf(sm,"%d",&m);
      while(K--)scanf("%d%d",&i,&j),a[i-1][j-1]=1;
      for(S=0;S<(1<<(m+m));S++){
        for(j=1,i=0;i<m;i++)if(get(S,i)==3){j=0;break;}
        if(j)q[++cnt]=S,h[S]=cnt;
      }
      clr();
      nxt();
      for(S=i=0;i<m;i++)S|=1<<(i+i);
      g[h[S]][0]=0;
      for(i=0;i<n;i++)for(j=0;j<m;j++){
        clr();
        for(k=1;k<=cnt;k++)for(t=0;t<2;t++)if(~g[k][t]){
          S=q[k],x=get(S,j),E=S^(x<<(j+j));
          if(x==2){
            if(a[i][j])continue;
            up(f[h[E^(1<<(j+j))]][x>0],g[k][t]);
          }else{
            up(f[h[E]][x>0],g[k][t]);
            if(a[i][j])continue;
            if(i>0)if(!x&&!a[i-1][j])up(f[h[E^(2<<(j+j))]][1],g[k][t]+1);
            if(j>=2)if(!get(S,j-1)&&!a[i][j-1]&&!get(S,j-2)&&!a[i][j-2]){
              up(f[h[E^(1<<(j+j-4)^(1<<(j+j-2)^(1<<(j+j))))]][x>0],g[k][t]+1);
            }
            if(j>=1)if(!get(S,j-1)&&!a[i][j-1]){
              up(f[h[E^(2<<(j+j-2))^(1<<(j+j))]][x>0],g[k][t]+1);
              up(f[h[E^(1<<(j+j-2))^(2<<(j+j))]][x>0],g[k][t]+1);
              if(i>0){
                if(!t&&!a[i-1][j-1]){
                  up(f[h[E^(1<<(j+j-2))^(1<<(j+j))]][x>0],g[k][t]+1);
                }
                if(!x&&!a[i-1][j]){
                  up(f[h[E^(1<<(j+j-2))^(1<<(j+j))]][1],g[k][t]+1);
                }
              }
            }
          }
        }
        nxt();
      }
      for(k=1;k<=cnt;k++){
        S=q[k];
        for(j=1,i=0;i<m;i++)if(get(S,i)==2){j=0;break;}
        if(j)for(t=0;t<2;t++)up(ans,g[k][t]);
      }
      printf("%d",ans);
    }
    }
    int main(){
      scanf("%s%s%d%s",sm,sn,&K,type);
      if(type[0]=='A')SubA::solve();
      if(type[0]=='B')SubB::solve();
      if(type[0]=='C')SubC::solve();
      return 0;
    }
    

      

  • 相关阅读:
    PCA (主成分分析)详解 (写给初学者) 结合matlab(转载)
    解释一下核主成分分析(Kernel Principal Component Analysis, KPCA)的公式推导过程(转载)
    主成分分析(PCA)原理详解(转载)
    神经网络的6种有监督训练算法
    PyCharm下载与激活
    matlab中元胞数组的创建与内容读取
    创新式开发探索(四) —— 探索式学习
    耐心,细心,贴心,静心
    使用 JsPlumb 绘制拓扑图的通用方法
    使用 amcharts 和 highcharts 绘制多曲线时间趋势图的通用方法
  • 原文地址:https://www.cnblogs.com/clrs97/p/5791747.html
Copyright © 2011-2022 走看看