hdu4057Rescue the Rabbit(ac自动机+dp)

链接

当时是因为没有做出来这道题才开了自动机的专题,现在看看还是比较简单的。

因为每个病毒串只算一次,只有10个病毒串,可以状压一下哪些状态是可以达到的,最后取一个最大值。

  1 #include <iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<stdlib.h>
  6 #include<vector>
  7 #include<cmath>
  8 #include<queue>
  9 #include<set>
 10 #include<string>
 11 using namespace std;
 12 #define N 1005
 13 #define LL long long
 14 #define INF 0xfffffff
 15 const double eps = 1e-8;
 16 const double pi = acos(-1.0);
 17 const double inf = ~0u>>2;
 18 const int child_num = 4;
 19 char vir[115];
 20 int v[12];
 21 class AC
 22 {
 23     private:
 24     int ch[N][child_num];
 25     int fail[N];
 26     int Q[N];
 27     int val[N];
 28     int sz;
 29     int id[128];
 30     int dp[2][N][1<<10];
 31     char s[N];
 32     public:
 33     void init()
 34     {
 35         fail[0] = 0;
 36         id['A'] = 0,id['G'] = 1,id['T'] = 2,id['C'] = 3;
 37     }
 38     void reset()
 39     {
 40         memset(ch[0],0,sizeof(ch[0]));
 41         memset(val,0,sizeof(val));
 42         sz = 1;
 43     }
 44     void insert(char *a,int key)
 45     {
 46         int p = 0;
 47         for(; *a ; a++)
 48         {
 49             int d= id[*a];
 50             if(ch[p][d]==0)
 51             {
 52                 memset(ch[sz],0,sizeof(ch[sz]));
 53                 s[sz] = *a;
 54                 ch[p][d] = sz++;
 55             }
 56             p = ch[p][d];
 57         }
 58         val[p] = (1<<key);
 59     }
 60     void construct()
 61     {
 62         int i,head=0,tail = 0;
 63         for(i = 0; i  < child_num ;i++)
 64         {
 65             if(ch[0][i])
 66             {
 67                 fail[ch[0][i]] = 0;
 68                 Q[tail++] = ch[0][i];
 69             }
 70         }
 71         while(head!=tail)
 72         {
 73             int u = Q[head++];
 74             val[u]|=val[fail[u]];
 75             for(i = 0; i < child_num ; i++)
 76             {
 77                 if(ch[u][i])
 78                 {
 79                     fail[ch[u][i]] = ch[fail[u]][i];
 80                     Q[tail++] = ch[u][i];
 81                 }
 82                 else ch[u][i] = ch[fail[u]][i];
 83             }
 84         }
 85     }
 86     void work(int n,int m)
 87     {
 88         int i,j,g;
 89         memset(dp,0,sizeof(dp));
 90         dp[0][0][0] = 1;
 91         for(i = 0 ;i < n ;i++)
 92         {
 93             memset(dp[(i+1)%2],0,sizeof(dp[(i+1)%2]));
 94             for(j = 0 ;j < sz ; j++)
 95             {
 96                 for(int e = 0 ; e < (1<<m) ; e++)
 97                 {
 98                     if(!dp[i%2][j][e]) continue;
 99                     for(g = 0 ; g < child_num ; g++)
100                     {
101                         int o = val[ch[j][g]];
102                         dp[(i+1)%2][ch[j][g]][e|o] = dp[i%2][j][e];
103                     }
104                 }
105             }
106         }
107         int cnt = -INF;
108         for(i = 0 ;i < sz ; i++)
109         {
110             for(j = 0 ;j < (1<<m) ; j++)
111             {
112                 int ans = 0;
113                 if(!dp[n%2][i][j]) continue;
114                 for(g = 0 ; g < m ;g++)
115                 {
116                     if(j&(1<<g))
117                     ans+=v[g];
118                 }
119                 cnt = max(ans,cnt);
120             }
121         }
122         if(cnt<0)
123         puts("No Rabbit after 2012!");
124         else
125         printf("%d\n",cnt);
126     }
127 }ac;
128 int main()
129 {
130     int n,i,m;
131     ac.init();
132     while(scanf("%d%d",&m,&n)!=EOF)
133     {
134         ac.reset();
135         for(i = 1;i <= m ;i++)
136         {
137             scanf("%s%d",vir,&v[i-1]);
138             ac.insert(vir,i-1);
139         }
140         ac.construct();
141         ac.work(n,m);
142     }
143     return 0;
144 }
View Code

 

posted @ 2014-05-25 09:47  _雨  阅读(221)  评论(0编辑  收藏  举报