hdu 4511 小明系列故事——女友的考验(AC自动机+dp)

题目链接:hdu 4511 小明系列故事——女友的考验

题意:

中文不解释。

题解:

考虑将那些限制的条件插进AC自动机里面,然后在AC自动机上dp一下最短路就行了。

考虑dp[i][j]表示当前在第i个点上,在AC自动机的第j个点上的最短路。

然后dp转移看代码。

 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=a;i<=b;i++)
 3 using namespace std;
 4 typedef pair<double,double>P;
 5 const int AC_N=1000,tyn=50;
 6 int n,m,s[50];
 7 P a[60];
 8 double dp[55][505],inf=1e18;
 9 
10 struct AC_automation{
11     int tr[AC_N][tyn],cnt[AC_N],Q[AC_N],fail[AC_N],tot;
12     void nw(){cnt[++tot]=0,fail[tot]=0;memset(tr[tot],0,sizeof(tr[tot]));}
13     void init(){tot=-1,fail[0]=-1,nw();}
14     void insert(int *s,int x=0){
15         for(int i=0,w;s[i];x=tr[x][w],i++)
16             if(!tr[x][w=s[i]])nw(),tr[x][w]=tot;
17         cnt[x]++;
18     }
19     void build(int head=1,int tail=0){
20         for(int i=0;i<tyn;i++)if(tr[0][i])Q[++tail]=tr[0][i];
21         while(head<=tail)for(int x=Q[head++],i=0;i<tyn;i++)
22             if(tr[x][i])
23             {
24                 fail[tr[x][i]]=tr[fail[x]][i],Q[++tail]=tr[x][i];
25                 cnt[tr[x][i]]+=cnt[tr[fail[x]][i]];
26             }
27             else tr[x][i]=tr[fail[x]][i];
28     }
29     double dis(P &a,P &b)
30     {
31         return sqrt((a.first-b.first)*(a.first-b.first)
32               +(a.second-b.second)*(a.second-b.second));
33     }
34     void solve()
35     {
36         F(i,0,n)F(j,0,tot)dp[i][j]=inf;
37         dp[1][tr[0][1]]=0;
38         F(i,1,n-1)F(j,0,tot)if(dp[i][j]!=inf)
39         {
40             F(k,i+1,n)
41             {
42                 int nxt=tr[j][k];
43                 if(cnt[nxt])continue;
44                 dp[k][nxt]=min(dp[k][nxt],dp[i][j]+dis(a[i],a[k]));
45             }
46         }
47         double ans=inf;
48         F(j,0,tot)ans=min(ans,dp[n][j]);
49         if(ans==inf)puts("Can not be reached!");
50         else printf("%.2f\n",ans);
51     }
52 }AC;
53 
54 int main()
55 {
56     while(scanf("%d%d",&n,&m),n+m)
57     {
58         F(i,1,n)scanf("%lf%lf",&a[i].first,&a[i].second);
59         AC.init();
60         F(i,1,m)
61         {
62             memset(s,0,sizeof(s));
63             int num,x;
64             scanf("%d",&num);
65             F(j,1,num)scanf("%d",s+j-1);
66             AC.insert(s);
67         }
68         AC.build(),AC.solve();
69     }
70     return 0;
71 }
View Code

 

posted @ 2017-10-16 19:16  bin_gege  阅读(154)  评论(0编辑  收藏  举报