zoukankan      html  css  js  c++  java
  • HDU-4511-ac自动机+dp

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

    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
     
        将女友的要求建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
    ",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 }
  • 相关阅读:
    作业16
    递归函数
    三元表达式与生成式
    迭代器与生成器
    作业15
    装饰器
    作业14
    string的入门与进阶
    修理牧场(优先队列)
    旅游规划
  • 原文地址:https://www.cnblogs.com/zzqc/p/8986500.html
Copyright © 2011-2022 走看看