HDU4511 AC自动机+dijkstra

题意:

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!” (引号不用输出)。

  1 #include <bits/stdc++.h>
  2 #include <cstdio>
  3 #include <iostream>
  4 #include <algorithm>
  5 #define ll long long
  6 #define lson l, m, rt<<1
  7 #define rson m+1, r, rt<<1|1
  8 #define st first
  9 #define nd second
 10 #define mp make_pair
 11 #define pii pair<int, int>
 12 #define pdi pair<double, int>
 13 #define gg puts("gg");
 14 //#define local
 15 //#define out1
 16 using namespace std;
 17 const int N  = 6e4+10;
 18 const int inf = 0x3f3f3f3f;
 19 int id(int c){
 20     return c-1;
 21 }
 22 struct Tire{
 23     int nex[N][50], fail[N],end[N], ch[N];
 24     int root, L, tot;
 25     int newnode(){
 26         memset(nex[L], -1, sizeof(nex[L]));
 27         end[L] = 0;
 28         ch[L] = 0;
 29         return L++;
 30     }
 31     void init(){
 32         L = tot = 0;
 33         root = newnode();
 34     }
 35     void insert(int* s, int len, int tag){
 36         int now = root;
 37         for(int i = 0; i < len; i++){
 38             int p = id(s[i]);
 39             if(nex[now][p] == -1)
 40                 nex[now][p] = newnode();
 41             now = nex[now][p];
 42             ch[now] = p;
 43         }
 44         end[now] = tag;
 45     }
 46     void build(){
 47         queue<int> Q;
 48         fail[root] = root;
 49         for(int i = 0; i < 50; i++){
 50             int& u = nex[root][i];
 51             if(u == -1)
 52                 u = root;
 53             else{
 54                 fail[u] = root;
 55                 Q.push(u);
 56             }
 57         }
 58         while(!Q.empty()){
 59             int now = Q.front();
 60             Q.pop();
 61             for(int i = 0; i < 50; i++){
 62                 int& u = nex[now][i];
 63                 if(u == -1)
 64                     u = nex[ fail[now] ][i];
 65                 else{
 66                     fail[u] = nex[ fail[now] ][i];
 67                     end[u] |= end[ fail[u] ];
 68                     Q.push(u);
 69                 }
 70             }
 71         }
 72     }
 73 };
 74 Tire ac;
 75 ll x[55], y[55];
 76 double w[55][55];
 77 int s[10];
 78 vector< pdi > ve[505];
 79 priority_queue< pdi, vector< pdi >, greater< pdi > >Q;
 80 double d[505];
 81 double dijkstra(int S){
 82     int i, x;
 83     for(i = 0; i < 505; i++) d[i] = 1e30;
 84     Q.push(mp(d[S]=0,S));
 85     while(!Q.empty()){
 86         pdi t = Q.top(); Q.pop();
 87         if(d[x = t.nd] < t.st) continue;
 88         for(i = 0; i < ve[x].size(); i++)
 89             if(d[x]+ve[x][i].st < d[ve[x][i].nd]){
 90                 d[ve[x][i].nd] = d[x]+ve[x][i].st;
 91                 Q.push( mp(d[ve[x][i].nd], ve[x][i].nd) );
 92             }
 93     }
 94 }
 95 int main(){
 96     int n, m, ca = 1;
 97     while(~scanf("%d%d", &n, &m), n+m){
 98         for(int i = 1; i <= n; i++)
 99             scanf("%lld%lld", x+i, y+i);
100         for(int i = 0; i <= n; i++)
101             for(int j = 0; j <= n; j++) w[i][j] = 1e30;
102         for(int i = 1; i <= n; i++)
103             for(int j = i+1; j <= n; j++)
104                 w[i][j] = sqrt( 1.0*(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]) );
105
106         ac.init();
107         for(int i = 1; i <= n; i++){
108             s[0] = i;
109             ac.insert(s, 1, 0);
110         }
111
112         for(int i = 1; i <= m; i++){
113             int k; scanf("%d", &k);
114             for(int j = 0; j < k; j++)
115                 scanf("%d", s+j);
116             ac.insert(s, k, 1);
117         }
118         ac.build();
119         for(int i = 0; i < ac.L; i++) ve[i].clear();
120         for(int i = 1; i < ac.L; i++){
121             int u = ac.ch[i]+1;
122             for(int j = u+1; j <= n; j++) {
123                 int to = ac.nex[i][id(j)];
124                 if(!ac.end[to]) ve[i].push_back( mp(w[u][j], to) );
125             }
126         }
127
128         dijkstra(ac.nex[0][id(1)]);
129         double ans = 1e30;
130         for(int i = 1; i < ac.L; i++){
131             if(ac.ch[i] == id(n))
132                 ans = min(ans, d[i]);
133         }
134         if(ans < 1e25)
135             printf("%.2f\n", ans);
136         else
137             puts("Can not be reached!");
138     }
139     return 0;
140 }

后记:发现debug能力实在太弱了...调半天没看出来哪错了...代码能力不够啊!!!

时间: 2024-10-17 23:26:30

HDU4511 AC自动机+dijkstra的相关文章

HDU4511 小明系列故事——女友的考验(AC自动机+DP)

题目大概说有平面有n个点,从1点出发走到n点,每一步只能走到序号比当前更大的点且走的序列不能包含给定的m个序列中的任何一个,问1走到n的最短路. 用m个序列建个AC自动机,后缀包含整个序列的结点标记一下,然后用dp[u][S]表示走到u点且走的序列的后缀状态是自动机上第S个结点的最短路,这样在AC自动机上跑着转移就OK了. 1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<que

hdu-4511(AC自动机+最短路)

题意:让你求从1走到n的最短路,但是有些路径是不能走的,且走到每次走只能走比当前点大的点 解题思路:看到有些路径是不能走的,想到用AC自动机标记结点,跑出一个trie图来,在trie图上进行路径更新,dist[i][j]表示在trie状态结点j的时候,到正常结点i的花费 代码: #include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<queue

[C#] 逆袭——自制日刷千题的AC自动机攻克HDU OJ

前言 做过杭电.浙大或是北大等ACM题库的人一定对“刷题”不陌生,以杭电OJ为例:首先打开首页(http://acm.hdu.edu.cn/),然后登陆,接着找到“Online Exercise”下的“Problem Archive”,然后从众多题目中选择一个进行读题.构思.编程.然后提交.最后查看题解状态,如果AC了表示这一题被攻克了,否则就要重做了~一般情况下,“刷题”要求精神高度集中且经验丰富,否则很难成功AC,有时候甚至做一题要浪费半天的时间!(有时网速卡了,比抢火车票还要急!) 楼主在

暑假集训day9补充(AC自动机)

推荐网站http://blog.csdn.net/niushuai666/article/details/7002823 AC自动机嘛,此AC(aho-corasick)非彼AC(Accepted). 我也不是很会解释 有一题是必须打的hdu2222. #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int mn=

ac自动机基础模板(hdu2222)

In the modern time, Search engine came into the life of everybody like Google, Baidu, etc. Wiskey also wants to bring this feature to his image retrieval system. Every image have a long description, when users type some keywords to find the image, th

HDU 2825 Wireless Password AC自动机+dp

训练赛第二场的I题,上完体育课回来就把这题过了,今天训练赛rank1了,还把大大队虐了,而且我还过了这道题 (虽然我也就过了这道题...),第一次在比赛中手写AC自动机还带dp的,心情大好. 给一个字符串集合,求包含该集合超过K个字符的,长度为L的字符串的个数. 显然是在AC自动机上跑dp,设dp[u][L][k]表示当前在结点u,还要走L步,当前状态为k的个数.一开始第三维表示的是包含k个字符串,但是题目要求不含重复的,那就只能状压了.转移为dp[u][L][k]+=dp[v][L-1][nk

HDU 2896-病毒侵袭(ac自动机)

题意: 给定多个模式串,每给一个母串,输出包含模式串的编号,最后输出包含模式串的母串的数量. 分析: ac自动机模板 #include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <st

hdu2222 Keywords Search &amp; AC自动机学习小结

传送门:http://http://acm.hdu.edu.cn/showproblem.php?pid=2222 思路:AC自动机入门题,直接上AC自动机即可. 对于构建AC自动机,我们要做的只有三件事: 1)构建字典树 2)构建失败指针 3)构建trie图(这道题好像不做这一步也能A...但是这一步不做是会被卡成O(n^2)的...) 1)第一步还是比较好理解的 根是虚根,边代表字母,那么根到终止节点的路径就是一个字符串,这样对于前缀相同的字符串我们就可以省下存公共前缀的空间. 加入一个模式

hdoj 2896 病毒侵袭(AC自动机)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2896 思路分析:题目为模式匹配问题,对于一个给定的字符串,判断能匹配多少个模式:该问题需要静态建树,另外需要对AC自动机的模板加以修改, 对于每个匹配的模式的最后一个单词的fail指针指向root,即可实现一个字符串进行多次模式匹配: 代码如下: #include <queue> #include <cstdio> #include <cstring> #include &