hdu4511小明系列故事——女友的考验(ac自动机+最短路)

链接

预处理出来任意两点的距离,然后可以顺着trie树中的节点走,不能走到不合法的地方,另开一维表示走到了哪里,依次来更新。

注意判断一下起点是不是合法。

  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 using namespace std;
11 #define N 510
12 #define LL long long
13 const double eps = 1e-8;
14 const double pi = acos(-1.0);
15 const double INF = 1e21;
16 const int child_num = 51;
17 double w[55][55];
18 class AC
19 {
20 private:
21 int ch[N][child_num];
22 int fail[N];
23 int val[N];
24 int id[128];
25 int Q[N];
26 double dis[55][N];
27 int sz;
28 public:
29 void init()
30 {
31 fail[0] = 0;
32 for(int i = 0 ; i< child_num ; i++)
33 id[i] = i;
34 }
35 void reset()
36 {
37 memset(ch[0],0,sizeof(ch[0]));
38 memset(val,0,sizeof(val));
39 sz = 1;
40 }
41 void insert(int *a,int k,int key)
42 {
43 int i,p=0;
44 for(i = 1;i <= k; i++)
45 {
46 int d = a[i];
47 if(ch[p][d]==0)
48 {
49 memset(ch[sz],0,sizeof(ch[sz]));
50 ch[p][d]= sz++;
51 }
52 p = ch[p][d];
53 }
54 val[p] = key;
55 }
56 void construct()
57 {
58 int i,head= 0 ,tail = 0;
59 for(i = 1 ;i < child_num ; i++)
60 {
61 if(ch[0][i])
62 {
63 fail[ch[0][i]] = 0;
64 Q[tail++] = ch[0][i];
65 }
66 }
67 while(head!=tail)
68 {
69 int u = Q[head++];
70 val[u]|=val[fail[u]];
71 for(i = 1; i < child_num ; i++)
72 {
73 if(ch[u][i])
74 {
75 fail[ch[u][i]] = ch[fail[u]][i];
76 Q[tail++] = ch[u][i];
77 }
78 else ch[u][i] = ch[fail[u]][i];
79 }
80 }
81 }
82 void work(int n)
83 {
84 int i,j,g;
85 for(i = 1; i <= n ;i++)
86 for(j = 0 ; j <= sz ;j++)
87 dis[i][j] = INF;
88 if(val[1])
89 {
90 puts("Can not be reached!");
91 return ;
92 }
93 dis[1][ch[0][1]] = 0;
94 for(i = 1 ; i <= n ;i++)
95 {
96 for(j = 0; j < sz ;j++)
97 {
98 for(g = 1; g <= n ;g++)
99 {
100 int np = ch[j][g];
101 if(val[np]) continue;
102 dis[g][np] = min(dis[g][np],dis[i][j]+w[i][g]);
103 }
104 }
105 }
106 double ans = INF;
107 for(i = 0 ; i < sz ; i++)
108 {
109 ans = min(ans,dis[n][i]);
110 }
111 if(fabs(ans-INF)<eps) puts("Can not be reached!");
112 else
113 printf("%.2f\n",ans);
114 }
115 }ac;
116 struct node
117 {
118 double x,y;
119 }pp[55];
120 double cdis(node a,node b)
121 {
122 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
123 }
124 int a[10];
125 int main()
126 {
127 int n,m,k,i,j;
128 ac.init();
129 while(scanf("%d%d",&n,&m)&&n&&m)
130 {
131 ac.reset();
132 for(i = 1 ;i <= n; i++)
133 {
134 scanf("%lf%lf",&pp[i].x,&pp[i].y);
135 }
136 for(i = 1; i <= n ;i++)
137 for(j = 1; j <= n ;j++)
138 w[i][j] = cdis(pp[i],pp[j]);
139 for(i = 1; i <= m ; i++)
140 {
141 scanf("%d",&k);
142 for(j= 1 ;j <= k; j++)
143 scanf("%d",&a[j]);
144 ac.insert(a,k,1);
145 }
146 ac.construct();
147 ac.work(n);
148 }
149 return 0;
150 }

时间: 2024-11-09 02:04:59

hdu4511小明系列故事——女友的考验(ac自动机+最短路)的相关文章

HDU - 4511 小明系列故事――女友的考验(AC自动机+DP)

Description 终于放寒假了,小明要和女朋友一起去看电影.这天,女朋友想给小明一个考验,在小明正准备出发的时候,女朋友告诉他,她在电影院等他,小明过来的路线必须满足给定的规则: 1.假设小明在的位置是1号点,女朋友在的位置是n号点,则他们之间有n-2个点可以走,小明每次走的时候只能走到比当前所在点编号大的位置: 2.小明来的时候不能按一定的顺序经过某些地方.比如,如果女朋友告诉小明不能经过1 -> 2 -> 3,那么就要求小明来的时候走过的路径不能包含有1 -> 2 ->

HDU ACM 4511 小明系列故事——女友的考验-&gt;AC自动机+DP

分析:参考别人的搞. 1.AC自动机: 使用AC自动机来压缩路段,如禁掉的路段是1->2->3,那么插入字符串(123) ,注意点只有1~50,所以0~50用ASCII 压缩成字符串即可. 这样就能够完成禁止路段的在线状态转移. 2.DP部分: 两点之间的最短路.dp[i][j]表示在地点i,当前字符是j的状态. 初始化:fill(&dp0][0],&dp[maxn-1][maxp-1],inf),inf=1e12,memset不能用. 边界:首先找出出发点在Pool中的位置,

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

小明系列故事--女友的考验 Time Limit: 500/200 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 863 Accepted Submission(s): 192 Problem Description 终于放寒假了,小明要和女朋友一起去看电影.这天,女朋友想给小明一个考验,在小明正准备出发的时候,女朋友告诉他,她在电影院等他,小明过来的路线必须满足给定的规则: 1.假

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 小明系列故事——女友的考验

小明系列故事——女友的考验 Time Limit: 500/200 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 822    Accepted Submission(s): 176 Problem Description 终于放寒假了,小明要和女朋友一起去看电影.这天,女朋友想给小明一个考验,在小明正准备出发的时候,女朋友告诉他,她在电影院等他,小明过来的路线必须满足给定的规则

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

小明系列故事--女友的考验 Time Limit: 500/200 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 1734    Accepted Submission(s): 466 Problem Description 终于放寒假了,小明要和女朋友一起去看电影.这天,女朋友想给小明一个考验,在小明正准备出发的时候,女朋友告诉他,她在电影院等他,小明过来的路线必须满足给定的规

AC自动机 + 二维最短路 HDU 4511 小明系列故事――女友的考验

这个题还是比较好想的. 首先将所有不可行方案建立AC自动机,然后跑最短路. 首先将小明放在(sta = 0,pos = 0)处,sta表示AC自动机上点的编号,pos表示坐标点的编号. 根据pos枚举下一次可以到达的地方[pos+1,n],然后sta在自动机上移动,如果某一步会使sta位于有标记的节点,那么这一步是不可行. #include <iostream> #include<time.h> #include<stdio.h> #include<string.

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

Problem Description 终于放寒假了,小明要和女朋友一起去看电影.这天,女朋友想给小明一个考验,在小明正准备出发的时候,女朋友告诉他,她在电影院等他,小明过来的路线必须满足给定的规则: 1.假设小明在的位置是1号点,女朋友在的位置是n号点,则他们之间有n-2个点可以走,小明每次走的时候只能走到比当前所在点编号大的位置: 2.小明来的时候不能按一定的顺序经过某些地方.比如,如果女朋友告诉小明不能经过1 -> 2 -> 3,那么就要求小明来的时候走过的路径不能包含有1 ->

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

题意:从 1 走到 n,要求所走路径不能出现给定的路径,求最短路 思路:因为要求不能出现给定路径,那么我可以求助ac自动机完成判断. 我们可以在build的时候标记哪些路径不能出现,显然下面这种表示后缀不能出现,那么他也不能出现 if(node[node[u].fail].cnt && u) node[u].cnt = 1; //都不能取 然后再把图建完整.因为如果一个路径不在Trie中有两种情况,一种是他可能是某个不能走的串的前缀,那么我就重新指向这个不能走的串,比如Trie中只有AT,