1. 程式人生 > >HDU-4511-ac自動機+dp

HDU-4511-ac自動機+dp

當前 %d debug 保留 說明 必須 php cal pre

小明系列故事——女友的考驗

Time Limit: 500/200 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 2024 Accepted Submission(s): 556


Problem Description   終於放寒假了,小明要和女朋友一起去看電影。這天,女朋友想給小明一個考驗,在小明正準備出發的時候,女朋友告訴他,她在電影院等他,小明過來的路線必須滿足給定的規則:
  1、假設小明在的位置是1號點,女朋友在的位置是n號點,則他們之間有n-2個點可以走,小明每次走的時候只能走到比當前所在點編號大的位置;

  2、小明來的時候不能按一定的順序經過某些地方。比如,如果女朋友告訴小明不能經過1 -> 2 -> 3,那麽就要求小明來的時候走過的路徑不能包含有1 -> 2 -> 3這部分,但是1 -> 3 或者1 -> 2都是可以的,這樣的限制路徑可能有多條。
  這讓小明非常頭痛,現在他把問題交給了你。
  特別說明,如果1 2 3這三個點共線,但是小明是直接從1到3然後再從3繼續,那麽此種情況是不認為小明經過了2這個點的。
  現在,小明即想走最短的路盡快見到女朋友,又不想打破女朋友的規定,你能幫助小明解決這個問題嗎?

Input   輸入包含多組樣例,每組樣例首先包含兩個整數n和m,其中n代表有n個點,小明在1號點,女朋友在n號點,m代表小明的女朋友有m個要求;

  接下來n行每行輸入2個整數x 和y(x和y均在int範圍),代表這n個點的位置(點的編號從1到n);
  再接著是m個要求,每個要求2行,首先一行是一個k,表示這個要求和k個點有關,然後是順序給出的k個點編號,代表小明不能走k1 -> k2 -> k3 ……-> ki這個順序的路徑;
  n 和 m等於0的時候輸入結束。

  [Technical Specification]
  2 <= n <= 50
  1 <= m <= 100
  2 <= k <= 5

Output   對於每個樣例,如果存在滿足要求的最短路徑,請輸出這個最短路徑,結果保留兩位小數;否則,請輸出”Can not be reached!” (引號不用輸出)。

Sample Input 3 1 1 1 2 1 3 1 2 1 2 2 1 0 0 1 1 2 1 2 5 3 0 0 5 3 1 2 1 22 5 21 3 1 2 3 2 4 5 2 1 5 0 0

Sample Output 2.00 Can not be reached! 21.65

Source 2013騰訊編程馬拉松初賽第二場(3月22日)     將女友的要求建ac自動機,然後在樹上匹配,f[i][j]表示在i號點對應樹上的狀態j時候的最短路(從1開始),WA了半天原來是bfs的時候忘記把以失配指針的為結尾的單詞狀態轉移到當前節點上,比如1-2-3-4 ,2-3 , 第一條路徑上的‘3‘顯然應該被標記為不能走的路(由於包含了禁路"2-3"),= =還是掌握的不熟練啊。   
  1 #include<iostream>
  2 #include<cstring>
  3 #include<queue>
  4 #include<cstdio>
  5 #include<stack>
  6 #include<set>
  7 #include<map>
  8 #include<cmath>
  9 #include<ctime>
 10 #include<time.h> 
 11 #include<algorithm>
 12 using namespace std;
 13 #define mp make_pair
 14 #define pb push_back
 15 #define debug puts("debug")
 16 #define LL long long 
 17 #define pii pair<int,int>
 18 #define eps 1e-10
 19 double inf=1e20;
 20 int N;
 21 struct Point{
 22     double x,y;
 23 }P[55];
 24 double dis(Point A,Point B){
 25     return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
 26 }
 27 double e[55][55];
 28 struct ach{
 29      int ch[1020][55],fail[1020],cnt[1020],tot;
 30      double f[55][1020]; 
 31       void init(){
 32           tot=0;
 33          newnode();
 34       }
 35       
 36      int newnode(){
 37          memset(ch[tot],-1,sizeof(ch[tot]));
 38          fail[tot]=-1;
 39          cnt[tot]=0;
 40          return tot++;
 41      }
 42      
 43      void insert(int a[],int n){
 44          int u=0;
 45          for(int i=1;i<=n;++i){
 46              if(ch[u][a[i]]==-1) ch[u][a[i]]=newnode();
 47              u=ch[u][a[i]];
 48          }
 49          cnt[u]=1;
 50      }
 51      void getfail(){
 52          queue<int>q;
 53          fail[0]=0;
 54          for(int i=1;i<=N;++i){
 55              if(ch[0][i]==-1){
 56                  ch[0][i]=0;
 57              }
 58              else{
 59                  fail[ch[0][i]]=0;
 60                  q.push(ch[0][i]);
 61              }
 62          }
 63         while(!q.empty()){
 64             int u=q.front();
 65             q.pop();
 66             cnt[u]|=cnt[fail[u]];
 67             for(int i=1;i<=N;++i){
 68                 if(ch[u][i]==-1){
 69                     ch[u][i]=ch[fail[u]][i];
 70                 }
 71                 else{
 72                     fail[ch[u][i]]=ch[fail[u]][i];
 73                     q.push(ch[u][i]);
 74                 }
 75             }
 76         }
 77      }
 78      
 79      void solve(){
 80          for(int i=1;i<=N;++i){
 81              for(int j=0;j<tot;++j){
 82                  f[i][j]=inf;
 83              }
 84          }
 85          f[1][ch[0][1]]=0;
 86          for(int i=1;i<=N;++i){
 87              for(int j=0;j<tot;++j){
 88                  if(f[i][j]<inf){
 89                      for(int k=i+1;k<=N;++k){
 90                          if(cnt[ch[j][k]]==0){
 91                              f[k][ch[j][k]]=min(f[k][ch[j][k]],f[i][j]+e[i][k]);
 92                          }
 93                      }
 94                  }
 95              }
 96          }
 97          
 98          double ans=inf;
 99          for(int j=0;j<tot;++j)
100          ans=min(ans,f[N][j]);
101          if(ans==inf) puts("Can not be reached!");
102          else printf("%.2f\n",ans);
103      }
104 }a;
105 int main()
106 {
107     int n,m,i,j,k;
108     int c[15];
109     while(cin>>n>>m){N=n;
110     a.init();
111         if(n==0&&m==0) break;
112         for(i=1;i<=n;++i) {e[i][i]=0;
113             scanf("%lf%lf",&P[i].x,&P[i].y);
114             for(j=1;j<i;++j){
115                 e[i][j]=e[j][i]=dis(P[i],P[j]);
116             }
117         }
118         for(i=1;i<=m;++i){
119             scanf("%d",&k);
120             for(j=1;j<=k;++j){
121                 scanf("%d",c+j);
122             }
123             a.insert(c,k);
124         }
125         
126         a.getfail();
127         a.solve();
128     }
129     return 0; 
130 }

HDU-4511-ac自動機+dp