HDU 4511 AC自动机+DP

来源:互联网 发布:2017年的同志网络剧 编辑:程序博客网 时间:2024/05/10 23:52

题意:

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4511
中文题。


思路:

常见的思路,不过要注意x和y要用double,否则溢出。


代码:

#include <bits/stdc++.h>using namespace std;const double INF = 1e20;const int MAXN = 505;const int K = 55;int n, m, k;struct ACauto {    int next[MAXN][K], fail[MAXN], end[MAXN];    int root, sz;    int newnode() {        for (int i = 1; i <= n; i++)            next[sz][i] = -1;        end[sz++] = 0;        return sz - 1;    }    void init() {        sz = 0;        root = newnode();    }    void insert(int *buf, int len) {        int now = root;        for (int i = 0; i < len; i++) {            int id = buf[i];            if (next[now][id] == -1)                next[now][id] = newnode();            now = next[now][id];        }        end[now]++;    }    void build() {        queue <int> Q;        fail[root] = root;        for (int i = 1; i <= n; i++) {            if (next[root][i] == -1)                next[root][i] = root;            else {                fail[next[root][i]] = root;                Q.push(next[root][i]);            }        }        while (!Q.empty()) {            int now = Q.front(); Q.pop();            end[now] += end[fail[now]];            for (int i = 1; i <= n; i++) {                if (next[now][i] == -1)                    next[now][i] = next[fail[now]][i];                else {                    fail[next[now][i]] = next[fail[now]][i];                    Q.push(next[now][i]);                }            }        }    }    void show() {        for (int i = 0; i < sz; i++) {            for (int j = 1; j <= n; j++)                printf("%d ", next[i][j]);            printf("\n");        }    }} ac;double g[K][K], dp[K][MAXN];void solve(int n) {    for (int i = 1; i <= n; i++) {        for (int j = 0; j < ac.sz; j++)            dp[i][j] = INF;    }    dp[1][ac.next[ac.root][1]] = 0;    for (int i = 1; i < n; i++) {        for (int j = 0; j < ac.sz; j++) {            if (ac.end[j] || dp[i][j] >= INF) continue;            for (int ni = i + 1; ni <= n; ni++) {                int nj = ac.next[j][ni];                if (ac.end[nj]) continue;                dp[ni][nj] = min(dp[ni][nj], dp[i][j] + g[i][ni]);            }        }    }    double ans = INF;    for (int i = 0; i < ac.sz; i++) {        ans = min(ans, dp[n][i]);    }    if (ans >= INF) puts("Can not be reached!");    else printf("%.2f\n", ans);}int x[K], y[K], a[MAXN];double dis(int x1, int y1, int x2, int y2) {    double dx = (double)x1 - x2, dy = (double)y1 - y2;    return sqrt(dx * dx + dy * dy);}int main() {    //freopen("in.txt", "r", stdin);    while (scanf("%d%d", &n, &m), n || m) {        for (int i = 1; i <= n; i++) {            scanf("%d%d", &x[i], &y[i]);        }        for (int i = 1; i <= n; i++) {            for (int j = i + 1; j <= n; j++)                g[i][j] = dis(x[i], y[i], x[j], y[j]);        }        ac.init();        for (int i = 1; i <= m; i++) {            scanf("%d", &k);            for (int j = 0; j < k; j++) {                scanf("%d", &a[j]);            }            ac.insert(a, k);        }        ac.build();        //ac.show();        solve(n);    }    return 0;}