Description
終於放寒假了,小明要和女朋友一起去看電影。這天,女朋友想給小明一個考驗,在小明正准備出發的時候,女朋友告訴他,她在電影院等他,小明過來的路線必須滿足給定的規則:Input
輸入包含多組樣例,每組樣例首先包含兩個整數n和m,其中n代表有n個點,小明在1號點,女朋友在n號點,m代表小明的女朋友有m個要求;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思路:設dp[i][j]表示到第i個點,自動機狀態到j的最小步數,注意的是因為我們是根據不合法的路徑構造自動機的,所以我們是不能走到某一條路徑的末尾的,根據這點來記錄我們的終止條件
#include#include #include #include #include #include #include #include using namespace std; const double inf = 1e20; pair p[100]; int n; double dp[55][1000]; double dis(pair a, pair b) { return sqrt((double)(1.0 * a.first - b.first) * (1.0 * a.first - b.first) + (double)(1.0 * a.second - b.second)*(1.0 * a.second - b.second)); } struct Tie { int nxt[1000][55], fail[1000], end[1000]; int root, cnt; int newNode() { for (int i = 1; i <= n; i++) nxt[cnt][i] = -1; end[cnt++] = 0; return cnt - 1; } void init() { cnt = 0; root = newNode(); } void insert(int a[], int len) { int now = root; for (int i = 0; i < len; i++) { if (nxt[now][a[i]] == -1) nxt[now][a[i]] = newNode(); now = nxt[now][a[i]]; } end[now] = 1; } void build() { queue q; fail[root] = root; for (int i = 1; i <= n; i++) { if (nxt[root][i] == -1) nxt[root][i] = root; else { fail[nxt[root][i]] = root; q.push(nxt[root][i]); } } while (!q.empty()) { int now = q.front(); q.pop(); end[now] |= end[fail[now]]; for (int i = 1; i <= n; i++) { if (nxt[now][i] == -1) nxt[now][i] = nxt[fail[now]][i]; else { fail[nxt[now][i]] = nxt[fail[now]][i]; q.push(nxt[now][i]); } } } } void solve() { for (int i = 1; i <= n; i++) for (int j = 0; j < cnt; j++) dp[i][j] = inf; dp[1][nxt[root][1]] = 0; for (int i = 1; i < n; i++) for (int j = 0; j < cnt; j++) if (dp[i][j] < inf) { for (int k = i+1; k <= n; k++) { int cur = nxt[j][k]; if (end[cur]) continue; dp[k][cur] = min(dp[k][cur], dp[i][j] + dis(p[i], p[k])); } } double ans = inf; for (int i = 0; i < cnt; i++) if (dp[n][i] < inf) ans = min(ans, dp[n][i]); if (ans == inf) printf("Can not be reached!\n"); else printf("%.2lf\n", ans); } } ac; int a[10]; int main() { int m; while (scanf("%d%d", &n, &m) != EOF && n + m) { for (int i = 1; i <= n; i++) scanf("%d%d", &p[i].first, &p[i].second); ac.init(); int k; while (m--) { scanf("%d", &k); for (int i = 0; i < k; i++) scanf("%d", &a[i]); ac.insert(a, k); } ac.build(); ac.solve(); } return 0; }