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 }
  • 相关阅读:
    Twitter的分布式自增ID算法snowflake (Java版)
    quartz获取缓存中所有运行中的Job
    Git简易的命令入门
    Eclipse新建Maven工程——git篇
    Spring基于AspectJ的AOP的开发——注解
    Quartz-Spring定时任务器持久化,通过Service动态添加,删除,启动暂停任务
    用windows命令解压chm文件
    播放器
    ab压力测试
    自定义事件javascript
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9664814.html
Copyright © 2011-2022 走看看