• 洛谷P3272 [SCOI2011]地板(插头dp)


    传送门

    感谢大佬的教导->这里

    容易注意到,本题的合法路径“L型地板”有一些特殊的地方:拐弯且仅拐弯一次。

    这由于一条路径只有两种状态:拐弯过和没拐弯过,因此我们可以尝试着这样定义新的插头:

    我们使用三进制,0代表没有插头,1代表没拐弯过的路径,2代表已经拐弯过的路径。

    依然设当前转移到格子(x,y),设y-1号插头状态为p1,y号插头状态为p2。

    那么会有下面的几种情况:

      情况1:p1==0&&p2==0

        这时我们有三种可选的策略:

          ①以当前位置为起点,从p1方向引出一条新的路径(把p1修改为1号插头)

          ②以当前位置为起点,从p2方向引出一条新的路径(把p2修改为1号插头)

          ③以当前位置为“L”型路径的转折点,向p1,p2两个方向均引出一个2号插头.

      情况2:p1==0&&p2==1

        由于p2节点还没有拐过弯,因此我们有2种可选的策略:

          ①继续直走,不拐弯,即上->下(把p1修改为1号插头,p2置0)

          ②选择拐弯,即上->右(把p2改为2号插头)

      情况3:p1==1&&p2==0

        这种情况和情况2类似

      情况4:p1==0&&p2==2

        由于p2节点已经拐过弯,所以我们有如下的两种策略:

        ①路径在此停止。那么我们以本格作为L型路径的一个端点。如果当前处于最后一个非障碍格子,如果没有其他的插头,我们此时就可以统计答案了。
        ②路径延续。由于p2已经转弯过,因此我们只能选择继续直走,即上->下(把p1修改为2号插头,p2置0)和之前相似的方法把独立插头传递下去即可。

      情况5:p1==2&&p2==0

        这种情况与情况4类似

      情况6:p1==1&&p2==1

        这种情况下,两块地板均没有拐过弯,因此我们可以在本格将这两块地板合并,形成一个合法的“L”型路径,并将本格看做他们的转折点。(把p1和p2都置为0)

    至此,新插头定义的状态转移已经讨论完成。

    不难发现,这种新的插头定义可以处理可能发生的所有可行情况。

    然后上代码

     1 //minamoto
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 const int N=105,HASH=200097,mod=20110520;
     7 int ans,n,m,lastx,lasty;char c[N][N];bool room[N][N];
     8 struct node{
     9     int val[HASH],key[HASH],Hash[HASH],sz;
    10     inline void init(){
    11         memset(val,0,sizeof(val)),memset(Hash,0,sizeof(Hash));
    12         memset(key,-1,sizeof(key)),sz=0;
    13     }
    14     inline void newhash(int id,int state){Hash[id]=++sz,key[sz]=state;}
    15     inline int &operator [](const int state){
    16         for(int i=state%HASH;;i=(i+1==HASH)?0:i+1){
    17             if(!Hash[i]) newhash(i,state);
    18             if(key[Hash[i]]==state) return val[Hash[i]];
    19         }
    20     }
    21 }f[2];
    22 inline int find(int state,int pos){return (state>>((pos-1)<<1))&3;}
    23 inline void set(int &state,int pos,int val){
    24     pos=(pos-1)<<1,state|=3<<pos,state^=3<<pos,state^=val<<pos;
    25 }
    26 void solve(int x,int y){
    27     int now=((x-1)*m+y)&1,last=now^1,tot=f[last].sz;
    28     f[now].init();
    29     for(int i=1;i<=tot;++i){
    30         int state=f[last].key[i],val=f[last].val[i];
    31         int plug1=find(state,y),plug2=find(state,y+1);
    32         if(!room[x][y]){
    33             if(!plug1&&!plug2) (f[now][state]+=val)%=mod;
    34         }
    35         else{
    36             if(!plug1&&!plug2){
    37                 if(room[x+1][y]) set(state,y,1),set(state,y+1,0),(f[now][state]+=val)%=mod;
    38                 if(room[x][y+1]) set(state,y,0),set(state,y+1,1),(f[now][state]+=val)%=mod;
    39                 if(room[x][y+1]&&room[x+1][y]) set(state,y,2),set(state,y+1,2),(f[now][state]+=val)%=mod;
    40             }
    41             else if(!plug1&&plug2){
    42                 if(plug2==1){
    43                     if(room[x+1][y]) set(state,y,1),set(state,y+1,0),(f[now][state]+=val)%=mod;
    44                     if(room[x][y+1]) set(state,y,0),set(state,y+1,2),(f[now][state]+=val)%=mod;
    45                 }
    46                 else{
    47                     set(state,y,0),set(state,y+1,0),(f[now][state]+=val)%=mod;
    48                     if(x==lastx&&y==lasty&&!state) (ans+=val)%=mod;
    49                     if(room[x+1][y]) set(state,y,2),set(state,y+1,0),(f[now][state]+=val)%=mod;
    50                 }
    51             }
    52             else if(plug1&&!plug2){
    53                 if(plug1==1){
    54                     if(room[x][y+1]) set(state,y,0),set(state,y+1,1),(f[now][state]+=val)%=mod;
    55                     if(room[x+1][y]) set(state,y,2),set(state,y+1,0),(f[now][state]+=val)%=mod;
    56                 }
    57                 else{
    58                     set(state,y,0),set(state,y+1,0),(f[now][state]+=val)%=mod;
    59                     if(x==lastx&&y==lasty&&!state) (ans+=val)%=mod;
    60                     if(room[x][y+1]) set(state,y,0),set(state,y+1,2),(f[now][state]+=val)%=mod;
    61                 }
    62             }
    63             else if(plug1==1&&plug2==1){
    64                 set(state,y,0),set(state,y+1,0),(f[now][state]+=val)%=mod;
    65                 if(x==lastx&&y==lasty&&!state)(ans+=val)%=mod;
    66             }
    67         }
    68     }
    69 }
    70 int main(){
    71 //    freopen("testdata.in","r",stdin);
    72     scanf("%d%d",&n,&m);
    73     for(int i=1;i<=n;++i) scanf("%s",c[i]+1);
    74     for(int i=1;i<=n;++i)
    75     for(int j=1;j<=m;++j)
    76     room[i][j]=(c[i][j]=='_');
    77     if(m>n){
    78         for(int i=1;i<=n;++i)
    79         for(int j=i+1;j<=m;++j)
    80         swap(room[i][j],room[j][i]);
    81         swap(n,m);
    82     }
    83     int flag=1;
    84     for(int i=n;i&&flag;--i)
    85     for(int j=m;j&&flag;--j)
    86     if(room[i][j]){lastx=i,lasty=j;flag=0;}
    87     f[0].init(),f[0][0]=1;
    88     for(int i=1;i<=n;++i){
    89         for(int j=1;j<=m;++j) solve(i,j);
    90         if(i!=n)
    91         for(int j=1,last=(i*m)&1,tot=f[last].sz;j<=tot;++j)
    92         f[last].key[j]<<=2;
    93     }
    94     printf("%d
    ",ans);
    95     return 0;
    96 }
  • 相关阅读:
    CentOS6.0/RedHat Server 6.4安装配置过程 详细图解!
    关于Haproxy安装和配置:负载配置【haproxy.cfg】问题记录
    菜鸟学习Struts——bean标签库
    2013——2014总结
    高效程序员的45个习惯读书 ——敏捷开发修炼之道笔记之态度决定一切
    Hive深入浅出
    Java从入门到精通——调错篇之SVN 出现 Loced错误
    考试系统优化——准备工作
    深入解析:分布式系统的事务处理经典问题及模型(转载分享)
    黑客攻击 UVa11825
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9657491.html
Copyright © 2020-2023  润新知