zoukankan      html  css  js  c++  java
  • HDU4758 Walk Through Squares(AC自动机+状压DP)

    题目大概说有个n×m的格子,有两种走法,每种走法都是一个包含D或R的序列,D表示向下走R表示向右走。问从左上角走到右下角的走法有多少种走法包含那两种走法。

    D要走n次,R要走m次,容易想到用AC自动机上的DP解决:

    • 用两种走法的序列构造AC自动机
    • dp[i][j][S][k]表示D用了i个R用了j个,且当前走到自动机的S结点,已经包含的走法的状态集合是k的方案数
    • 转移就是走R或者走D了,我用我为人人来转移
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<queue>
     4 #include<algorithm>
     5 using namespace std;
     6 #define MAXN 222
     7 int tn,ch[MAXN][2],fail[MAXN],flag[MAXN];
     8 int idx[128];
     9 void insert(char *s,int k){
    10     int x=0;
    11     for(int i=0; s[i]; ++i){
    12         int y=idx[s[i]];
    13         if(ch[x][y]==0) ch[x][y]=++tn;
    14         x=ch[x][y];
    15     }
    16     flag[x]|=(1<<k);
    17 }
    18 void getfail(){
    19     memset(fail,0,sizeof(fail));
    20     queue<int> que;
    21     for(int i=0; i<2; ++i){
    22         if(ch[0][i]) que.push(ch[0][i]);
    23     }
    24     while(!que.empty()){
    25         int x=que.front(); que.pop();
    26         for(int i=0; i<2; ++i){
    27             if(ch[x][i]){
    28                 que.push(ch[x][i]);
    29                 fail[ch[x][i]]=ch[fail[x]][i];
    30                 flag[ch[x][i]]|=flag[ch[fail[x]][i]];
    31             }else ch[x][i]=ch[fail[x]][i];
    32         }
    33     }
    34 }
    35 
    36 int d[111][111][MAXN][4];
    37 
    38 int main(){
    39     idx['R']=0; idx['D']=1;
    40     int t,n,m;
    41     char str[111];
    42     scanf("%d",&t);
    43     while(t--){
    44         tn=0;
    45         memset(ch,0,sizeof(ch));
    46         memset(flag,0,sizeof(flag));
    47         scanf("%d%d",&n,&m);
    48         for(int i=0; i<2; ++i){
    49             scanf("%s",str);
    50             insert(str,i);
    51         }
    52         getfail();
    53         memset(d,0,sizeof(d));
    54         d[0][0][0][0]=1;
    55         for(int len=0; len<n+m; ++len){
    56             for(int i=0; i<=len; ++i){
    57                 int j=len-i;
    58                 if(j>m || i>n) continue;
    59                 for(int s=0; s<=tn; ++s){
    60                     for(int k=0; k<4; ++k){
    61                         d[i+1][j][ch[s][0]][k|flag[ch[s][0]]]+=d[i][j][s][k];
    62                         d[i+1][j][ch[s][0]][k|flag[ch[s][0]]]%=1000000007;
    63                         d[i][j+1][ch[s][1]][k|flag[ch[s][1]]]+=d[i][j][s][k];
    64                         d[i][j+1][ch[s][1]][k|flag[ch[s][1]]]%=1000000007;
    65                     }
    66                 }
    67             }
    68         }
    69         int res=0;
    70         for(int i=0; i<=tn; ++i){
    71             res+=d[n][m][i][3];
    72             res%=1000000007;
    73         }
    74         printf("%d
    ",res);
    75     }
    76     return 0;
    77 }
  • 相关阅读:
    口语详解|为什么“how to say”是错的?
    9 tips to improve spoken english
    splash 安装
    ubuntu 安装NVIDIA驱动过程
    【Python数据分析】时间模块datetime
    【Python数据分析】Pandas模块下的Series与DataFrame
    【Python】文件
    博客园Markdown样式美化
    【Python】异常处理
    【Python】eval函数
  • 原文地址:https://www.cnblogs.com/WABoss/p/5387697.html
Copyright © 2011-2022 走看看