zoukankan      html  css  js  c++  java
  • 洛谷P3190 [HNOI2007]神奇游乐园(插头dp)

    传送门

    大概是算第一道自己做出来的插头dp?

    (虽然都是照着抄板子的)

    (虽然有个地方死活没调出来最后只能看题解才发现自己错在哪里的)

    我就当你们都会插头dp了……

    因为必须得是一条路径,所以扫描线上的插头得两两对应,要用括号序列

    然后分情况讨论一下,记$p1$为当前关键格左边的插头,$p2$为当前关键格上面的插头

    $0$表示无插头,$1$表示左括号,$2$表示右括号

    1.$p1==0$且$p2==0$

    那么很明显我们可以把下方插头设为$1$右方插头设为$2$,就形成一个新的连通块了

    然后注意不设任何插头的状态也要转移(我就是在这里坑了一个晚上)

    2.$p1!=0$且$p2==0$

    那么我们有两种走法,一是直走,那么右插头的值就是原插头的值,一是拐弯,那么下面的插头的值就是左插头的值

    3.$p1==0$且$p2!=0$

    同上,不多说了

    4.$p1==1$且$p2==1$

    就是两个左括号撞到一起了,那么把$p2$对应的右括号改成左括号

    5.$p1==1$且$p2==2$

    这种情况就说明一条路径已经结束了,那么此时如果轮廓线上没有其他任何插头就可以更新答案了

    6.$p1==2$且$p2==1$

    两条路径在这里汇合,直接合并

    7.$p1==2$且$p2==2$

    两个右括号撞到一起了,那么把$p1$对应的左括号改成右括号

    然后……剩下的看代码好了(似乎我的插头dp写法和很多人不一样诶……)

     1 //minamoto
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #define ll long long
     6 #define inf 0x3f3f3f3f3f3f3f3f
     7 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
     8 const int mod=200097;
     9 int n,m,c[105][105];ll ans=-0x3f3f3f3f3f3f3f3f;
    10 struct Ha{
    11     int key[mod],sz,Hash[mod];ll val[mod];
    12     inline void init(){
    13         memset(val,0xef,sizeof(val)),memset(key,-1,sizeof(key));
    14         sz=0,memset(Hash,0,sizeof(Hash));
    15     }
    16     inline void newhash(int id,int state){Hash[id]=++sz,key[sz]=state,val[sz]=-inf;}
    17     ll &operator [](const int state){
    18         for(int i=state%mod;;i=(i+1==mod)?0:i+1){
    19             if(!Hash[i]) newhash(i,state);
    20             if(key[Hash[i]]==state) return val[Hash[i]];
    21         }
    22     }
    23 }f[2];
    24 inline int find(int state,int id){return (state>>((id-1)<<1))&3;}
    25 inline void set(int &state,int pos,int val){
    26     pos=(pos-1)<<1,state|=3<<pos,state^=3<<pos,state|=val<<pos;
    27 }
    28 int link(int state,int pos){
    29     int cnt=0,del=(find(state,pos)==1)?1:-1;
    30     for(int i=pos;i&&i<=m+1;i+=del){
    31         int plug=find(state,i);
    32         if(plug==1) ++cnt;
    33         else if(plug==2) --cnt;
    34         if(!cnt) return i;
    35     }
    36     return -1;
    37 }
    38 void solve(int x,int y){
    39     int now=((x-1)*m+y)&1,last=now^1,tot=f[last].sz;
    40     f[now].init();
    41     for(int i=1;i<=tot;++i){
    42         int state=f[last].key[i];ll val=f[last].val[i];
    43         int plug1=find(state,y),plug2=find(state,y+1);
    44         if(!plug1&&!plug2){
    45             cmax(f[now][state],val);
    46             if(x!=n&&y!=m) set(state,y,1),set(state,y+1,2),cmax(f[now][state],val+c[x][y]);
    47         }
    48         else if(plug1&&!plug2){
    49             if(x!=n) cmax(f[now][state],val+c[x][y]);
    50             if(y!=m) set(state,y,0),set(state,y+1,plug1),cmax(f[now][state],val+c[x][y]);
    51         }
    52         else if(!plug1&&plug2){
    53             if(y!=m) cmax(f[now][state],val+c[x][y]);
    54             if(x!=n) set(state,y,plug2),set(state,y+1,0),cmax(f[now][state],val+c[x][y]);
    55         }
    56         else if(plug1==1&&plug2==1)
    57         set(state,link(state,y+1),1),set(state,y,0),set(state,y+1,0),cmax(f[now][state],val+c[x][y]);
    58         else if(plug1==1&&plug2==2){
    59             set(state,y,0),set(state,y+1,0);
    60             if(!state) cmax(ans,val+c[x][y]);
    61         }
    62         else if(plug1==2&&plug2==1) set(state,y,0),set(state,y+1,0),cmax(f[now][state],val+c[x][y]);
    63         else if(plug1==2&&plug2==2)
    64         set(state,link(state,y),2),set(state,y,0),set(state,y+1,0),cmax(f[now][state],val+c[x][y]);
    65     }
    66 }
    67 int main(){
    68 //    freopen("testdata.in","r",stdin);
    69     scanf("%d%d",&n,&m);
    70     for(int i=1;i<=n;++i)
    71     for(int j=1;j<=m;++j)
    72     scanf("%d",&c[i][j]);
    73     f[0].init(),f[0][0]=0;
    74     for(int i=1;i<=n;++i){
    75         for(int j=1;j<=m;++j) solve(i,j);
    76         if(i!=n){
    77             int now=(i*m)&1,tot=f[now].sz;
    78             for(int j=1;j<=tot;++j)
    79             f[now].key[j]<<=2;
    80         }
    81     }
    82     printf("%lld
    ",ans);
    83     return 0;
    84 }
  • 相关阅读:
    php命令注入
    mysql事物
    安装php环境
    移除服务器缓存实例
    show user profile synchronization tools
    manual start user profile import
    JSON is undefined. Infopath Form People Picker in SharePoint 2013
    asp.net web 应用站点支持域账户登录
    Load sharepoint envirement by powershell
    sharepoint 2016 download
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9664814.html
Copyright © 2011-2022 走看看