HDU 4511 小明系列故事——女友的考验 (AC自动机 + DP)题解
Posted kirinsb
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 4511 小明系列故事——女友的考验 (AC自动机 + DP)题解相关的知识,希望对你有一定的参考价值。
题意:从 1 走到 n,要求所走路径不能出现给定的路径,求最短路
思路:因为要求不能出现给定路径,那么我可以求助ac自动机完成判断。
我们可以在build的时候标记哪些路径不能出现,显然下面这种表示后缀不能出现,那么他也不能出现
if(node[node[u].fail].cnt && u) node[u].cnt = 1; //都不能取
然后再把图建完整。因为如果一个路径不在Trie中有两种情况,一种是他可能是某个不能走的串的前缀,那么我就重新指向这个不能走的串,比如Trie中只有AT,那么我走ATA相当于走AT再走回A;另一种是这个路径根本没出现过,那么相当于从0开始走。
if(!node[u].next[i]) if(u == 0) node[u].next[i] = 0; else node[u].next[i] = node[node[u].fail].next[i];
dp[i][j]表示走到i点在AC自动机上走到j点的最小路径。
代码:
#include<cmath> #include<set> #include<map> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include <iostream> #include<algorithm> using namespace std; typedef long long ll; typedef unsigned long long ull; const int maxn = 500 + 5; const int M = 50 + 5; const ull seed = 131; const double INF = 1e20; const int MOD = 1000000007; double x[M], y[M]; int s[M]; double dp[M][maxn]; int m, n; double dis(int i, int j) return sqrt((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j])); struct Aho struct state int next[M]; int fail, cnt; node[maxn]; int size; queue<int> q; void init() size = 0; newtrie(); while(!q.empty()) q.pop(); int newtrie() memset(node[size].next, 0, sizeof(node[size].next)); node[size].cnt = node[size].fail = 0; return size++; void insert(int s[], int len) int now = 0; for(int i = 0; i < len; i++) int c = s[i]; if(node[now].next[c] == 0) node[now].next[c] = newtrie(); now = node[now].next[c]; node[now].cnt = 1; void build() node[0].fail = -1; q.push(0); while(!q.empty()) int u = q.front(); q.pop(); if(node[node[u].fail].cnt && u) node[u].cnt = 1; //都不能取 for(int i = 0; i <= n; i++) if(!node[u].next[i]) if(u == 0) node[u].next[i] = 0; else node[u].next[i] = node[node[u].fail].next[i]; else if(u == 0) node[node[u].next[i]].fail = 0; else int v = node[u].fail; while(v != -1) if(node[v].next[i]) node[node[u].next[i]].fail = node[v].next[i]; break; v = node[v].fail; if(v == -1) node[node[u].next[i]].fail = 0; q.push(node[u].next[i]); void query() for(int i = 0; i <= n; i++) for(int j = 0; j < size; j++) dp[i][j] = INF; dp[1][node[0].next[1]] = 0; for(int i = 1; i <= n; i++) for(int j = 0; j < size; j++) if(dp[i][j] == INF) continue; for(int k = i + 1; k <= n; k++) if(node[node[j].next[k]].cnt) continue; dp[k][node[j].next[k]] = min(dp[k][node[j].next[k]], dp[i][j] + dis(i, k)); double ans = INF; for(int i = 0; i < size; i++) if(dp[n][i] < INF) ans = min(ans, dp[n][i]); if(ans == INF) printf("Can not be reached!\n"); else printf("%.2f\n", ans); ac; int main() while(~scanf("%d%d", &n, &m) && n + m) for(int i = 1; i <= n; i++) scanf("%lf%lf", &x[i], &y[i]); ac.init(); while(m--) int k; scanf("%d", &k); for(int i = 0; i < k; i++) scanf("%d", &s[i]); ac.insert(s, k); ac.build(); ac.query(); return 0;
以上是关于HDU 4511 小明系列故事——女友的考验 (AC自动机 + DP)题解的主要内容,如果未能解决你的问题,请参考以下文章
HDU 4511 小明系列故事——女友的考验 (AC自动机 + DP)题解