SCOI2011地板 题解

it2026-04-01  11

这是一道最经典的基于连通性的状态压缩dp。f[i][j][s]表示轮廓线到i,j格的时候,轮廓线上状态为s的方案数。

用一个四进制数表示s:

0表示该位置没有插头,1表示该位置的插头必须拐弯,2表示这个插头不必须被延长,3表示该插头必须被延长。

具体转移请见程序:

#include<iostream>#include<cstring>#include<cstdio>using namespace std;typedef long long LLint;const LLint MAXN=110;const LLint HASHSIZE=3000009;const LLint MOD=20110520;LLint n,m;char Cmd[MAXN][MAXN];int Map[MAXN][MAXN];LLint t[MAXN];LLint Hash[HASHSIZE];LLint State[2][HASHSIZE][2];int Now,Bef,Lx,Ly;LLint Total[2],Tot,Ans;void Push(LLint Pos,LLint Cnt){    int h=Pos%HASHSIZE;    while(Hash[h]){        if(State[Now][Hash[h]][0]==Pos){            State[Now][Hash[h]][1]=(State[Now][Hash[h]][1]+Cnt)%MOD;            return ;        }        ++h;        if(h>=HASHSIZE)            h=0;    }    Total[Now]++;    Hash[h]=Total[Now];    State[Now][Hash[h]][0]=Pos;    State[Now][Hash[h]][1]=Cnt%MOD;}int main(){    //freopen("floor10.in","r",stdin);    scanf("%I64d%I64d",&n,&m);    for(int i=1;i<=n;++i)        scanf("%s",&Cmd[i][1]);    if(n<m){        for(int i=1;i<=n;++i)            for(int j=1;j<=m;++j){                if(Cmd[i][j]=='_'){                    Map[j][n-i+1]=1;                }                else                    Map[j][n-i+1]=0;            }        swap(n,m);    }    else{        for(int i=1;i<=n;++i)            for(int j=1;j<=m;++j){                if(Cmd[i][j]=='_'){                    Map[i][j]=1; Lx=i; Ly=j;                }                else                    Map[i][j]=0;            }    }    for(int i=1;i<MAXN;++i)        t[i]=i<<1;    State[Now][1][1]=1;    Total[Now]++;    for(int i=1;i<=n;++i)        for(int j=1;j<=m;++j)            if(Map[i][j]){                Lx=i; Ly=j;            }    for(int i=1;i<=n;++i){        for(int j=1;j<=m;++j){            Now^=1; Bef=Now^1;            memset(Hash,0,sizeof(Hash));            Tot=Total[Bef];            Total[Bef]=Total[Now]=0;            for(int k=1;k<=Tot;++k){                LLint Pos=State[Bef][k][0];                LLint Cnt=State[Bef][k][1];                int Up=(Pos>>t[j])%4;                int Lt=(Pos>>t[j-1])%4;                State[Bef][k][0]=State[Bef][k][1]=0;                if(!Map[i][j]){                    if(!Up&&!Lt){                        Push(Pos,Cnt);                    }                    continue;                }                if(!Up&&!Lt){                    if(Map[i+1][j]){                        int Next=Pos^(1<<t[j-1]); Push(Next,Cnt);                    }                    if(Map[i][j+1]){                        int Next=Pos^(1<<t[j]); Push(Next,Cnt);                    }                    if(Map[i+1][j]&&Map[i][j+1]){                        int Next=Pos^(3*(1<<t[j-1]))^(3*(1<<t[j])); Push(Next,Cnt);                    }                    continue;                }                if(Up&&!Lt){                    if(Up==1){                        if(Map[i+1][j]){                            int Next=Pos^(1<<t[j-1])^(1<<t[j]); Push(Next,Cnt);                        }                        if(Map[i][j+1]){                            int Next=Pos^(1<<t[j])^((1<<t[j])*3); Push(Next,Cnt);                        }                    }                    if(Up==2){                        if(Map[i+1][j]){                            int Next=Pos^((1<<t[j-1])<<1)^((1<<t[j])<<1); Push(Next,Cnt);                        }                        if(Map[i][j]){                            int Next=Pos^((1<<t[j])<<1); Push(Next,Cnt);                        }                        if(Lx==i&&Ly==j)                            Ans=(Ans+Cnt)%MOD;                    }                    if(Up==3){                        if(Map[i+1][j]){                            int Next=Pos^((1<<t[j])*Up)^((1<<t[j-1])<<1); Push(Next,Cnt);                        }                        if(Map[i][j]){                            int Next=Pos^((1<<t[j])*Up); Push(Next,Cnt);                        }                        if(i==Lx&&j==Ly){                            Ans=(Ans+Cnt)%MOD;                        }                        continue;                    }                }                                if(!Up&&Lt){                    if(Lt==1){                        if(Map[i+1][j]){                            int Next=Pos^((1<<t[j-1])*3)^(1<<t[j-1]); Push(Next,Cnt);                        }                        if(Map[i][j+1]){                            int Next=Pos^(1<<t[j-1])^(1<<t[j]); Push(Next,Cnt);                        }                    }                    if(Lt==2){                        if(Map[i][j+1]){                            int Next=Pos^((1<<t[j-1])<<1)^((1<<t[j])<<1); Push(Next,Cnt);                        }                        if(Map[i][j]){                            int Next=Pos^((1<<t[j-1])<<1); Push(Next,Cnt);                        }                        if(Lx==i&&Ly==j)                            Ans=(Ans+Cnt)%MOD;                    }                    if(Lt==3){                        if(Map[i][j+1]){                            int Next=Pos^((1<<t[j-1])*3)^((1<<t[j])<<1); Push(Next,Cnt);                        }                        if(Map[i][j]){                            int Next=Pos^((1<<t[j-1])*3); Push(Next,Cnt);                        }                        if(Lx==i&&Ly==j){                            Ans=(Ans+Cnt)%MOD;                        }                    }                    continue;                }                if(Up==1&&Lt==1){                    int Next=Pos^(1<<t[j])^(1<<t[j-1]); Push(Next,Cnt);                    if(Lx==i&&Ly==j)                        Ans=(Ans+Cnt)%MOD;                }            }        }        for(int j=1;j<=Total[Now];++j)            State[Now][j][0]<<=2;    }    printf("%I64d",Ans);return 0;}

转载于:https://www.cnblogs.com/Return-0/archive/2013/04/18/3028642.html

相关资源:数据结构—成绩单生成器
最新回复(0)