zoukankan      html  css  js  c++  java
  • BZOJ2310 : ParkII

    单路径最大和问题,设f[i][j][S]表示到达(i,j),轮廓线状态为S的最优解。

    S用4进制m+1位数表示,0表示无插头,1表示左括号,2表示右括号,3表示独立插头。

    在DP之前先进行一次预处理,剔除无效状态,并预处理出与每个括号匹配的另一个括号的位置,有效状态只有8000个左右。

    然后分类讨论进行转移即可。

    #include<cstdio>
    const int N=9,M=8320,inf=-1000000000;
    int n,m,S,i,j,k,h,z,ans=inf,q[M],id[1<<(N*2)],pre[M],now[M];
    char can,c3,st[N+1],p[M][N],tmp[N];
    inline int bit(int x,int i){return x>>(i<<1)&3;}
    inline void up(int&a,int b){if(a<b)a=b;}
    inline void clr(){for(int k=1;k<=q[0];k++)now[k]=inf;}
    inline void nxt(){for(int k=1;k<=q[0];k++)pre[k]=now[k];}
    int main(){
      scanf("%d%d",&n,&m);
      S=1<<(2*(m+1));
      for(i=0;i<S;i++){
        can=1,st[0]=c3=0;
        for(j=0;j<=m;j++){
          k=bit(i,j);
          if(k==1)st[++st[0]]=j;
          if(k==2){
            if(!st[0]){can=0;break;}
            tmp[st[st[0]]]=j;tmp[j]=st[st[0]];
            st[0]--;
          }
          if(k==3)if((++c3)>2){can=0;break;}
        }
        if(can&&!st[0]){
          q[id[i]=++q[0]]=i;
          for(j=0;j<=m;j++)p[q[0]][j]=tmp[j];
        }
      }
      clr();
      now[1]=0;
      nxt();
      for(i=1;i<=n;i++){
        clr();
        for(k=1;k<=q[0];k++)if(pre[k]>inf&&!bit(q[k],m))now[id[q[k]<<2]]=pre[k];
        nxt();
        for(j=1;j<=m;j++){
          scanf("%d",&z),up(ans,z),clr();
          for(h=1;h<=q[0];h++)if(pre[h]>inf){
            int v=pre[h]+z,k=q[h],x=bit(k,j-1),y=bit(k,j),e=k^(x<<((j-1)<<1))^(y<<(j<<1));
            if(!x&&!y){
              up(now[h],v-z);
              up(now[id[e^(1<<((j-1)<<1))^(2<<(j<<1))]],v);
              up(now[id[e^(3<<((j-1)<<1))]],v);
              up(now[id[e^(3<<(j<<1))]],v);
            }else if(!x||!y){
              int t=x+y;
              up(now[id[e^(t<<((j-1)<<1))]],v);
              up(now[id[e^(t<<(j<<1))]],v);
              if(t==3){if(!e)up(ans,v);}
              else{
                if(x)up(now[id[e^(x<<(p[h][j-1]<<1))]],v);
                else up(now[id[e^(y<<(p[h][j]<<1))]],v);
              }
            }else if(x==1&&y==1)up(now[id[e^(3<<(p[h][j]<<1))]],v);
            else if(x==2&&y==1)up(now[id[e]],v);
            else if(x==2&&y==2)up(now[id[e^(3<<(p[h][j-1]<<1))]],v);
            else if(x==3&&y==3){if(!e)up(ans,v);}
            else if(x==3)up(now[id[e^(y<<(p[h][j]<<1))]],v);
            else if(y==3)up(now[id[e^(x<<(p[h][j-1]<<1))]],v);
          }
          nxt();
        }
      }
      return printf("%d",ans),0;
    }
    

      

  • 相关阅读:
    socket选项设置
    shell 备忘录
    VIM中cscope和tags数据库的添加
    MFC程序设计中的BeginPaint/EndPaint和GetDC/ReleaseDC的使用
    shell 命令行参数解析
    do{...}while(0)用法总结
    0长度数组的使用
    在线帮助文档
    GCC编译器帮助文档
    几款优秀的Linux基准测试工具
  • 原文地址:https://www.cnblogs.com/clrs97/p/4992021.html
Copyright © 2011-2022 走看看