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

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 <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <set>
#include <queue>
#include <cmath>
using namespace std;
const double inf = 1e20; pair<int, int> p[100];
int n;
double dp[55][1000]; double dis(pair<int, int> a, pair<int, int> 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<int> 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;
}

HDU - 4511 小明系列故事――女友的考验(AC自己主动机+DP)的更多相关文章

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

    小明系列故事——女友的考验 Time Limit: 500/200 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total ...

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

    小明系列故事——女友的考验 Time Limit: 500/200 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total ...

  3. HDU 4511 小明系列故事——女友的考验 ( Trie图 && DP )

    题意 :  给出编号从1 ~ n 的 n 个平面直角坐标系上的点,求从给出的第一个点出发到达最后一个点的最短路径,其中有两种限制,其一就是只能从编号小的点到达编号大的点,再者不能走接下来给出的 m 个 ...

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

    题意:从 1 走到 n,要求所走路径不能出现给定的路径,求最短路 思路:因为要求不能出现给定路径,那么我可以求助ac自动机完成判断. 我们可以在build的时候标记哪些路径不能出现,显然下面这种表示后 ...

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

    题目链接:https://vjudge.net/problem/HDU-4511 小明系列故事——女友的考验 Time Limit: 500/200 MS (Java/Others)    Memor ...

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

    链接 预处理出来任意两点的距离,然后可以顺着trie树中的节点走,不能走到不合法的地方,另开一维表示走到了哪里,依次来更新. 注意判断一下起点是不是合法. #include <iostream& ...

  7. 小明系列故事――女友的考验 HDU - 4511 AC自动机+简单DP

    题意:自己看题目,中文体面. 题解: 把所有不能走的路径放入AC自动机中. 然后DP[i][j]表示走到 i 这个点,且位于AC自动机 j 这个节点最短距离 然后直接DP即可.注意一点会爆int #i ...

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

    题目大概说有平面有n个点,从1点出发走到n点,每一步只能走到序号比当前更大的点且走的序列不能包含给定的m个序列中的任何一个,问1走到n的最短路. 用m个序列建个AC自动机,后缀包含整个序列的结点标记一 ...

  9. HDU-4511 小明系列故事——女友的考验 floyd变种-标号递增最短路

    题意:给定N个点,现在要求出从1号点到N号点的最短路.题目给的限制条件就是对于某条路径是不能够走的,但是可以选择某段路径走,另外就是所走的路径的标号必须是递增的. 分析:由于给定的是一些列的坐标点,这 ...

随机推荐

  1. Discuz常见小问题-如何为每个板块设置不同的图标

    进入后台的论坛-版块管理,选中要修改图标的板块,点击后面的编辑 在板块图标中找到图标文件,一般是PNG或者GIF,大小为32X32,提交之后效果如下

  2. SQL语句 怎么把从一个表中查出来数据插入到另一个表中

    (1).select * into destTbl from srcTbl(2).insert into destTbl(fld1, fld2) select fld1, 5 from srcTbl

  3. Qt通过ODBC连接SQL Server2008实践总结

    Qt连接数据库的方式很多,这里说明一种最常用也是最实用的方式,因为这种方式在Windows上开发程序使用起来非常方便,并且也是远程连接数据库所需要用到的方式. 前提工作: 在Win7下安装了SQL S ...

  4. hibernate 02之helloworld

    1.安装插件 安装方法说明(hibernatetools-.Final): Help --> Install New Software... Click Add... In dialog Add ...

  5. angularjs初始化时不显示模板内容, 不显示html, 不显示template

    template的内容可能在需要的数据准备好之前就显示出来了, ng-cloak可以解决这个问题 ng-cloak <div id="template1" ng-cloak& ...

  6. (转)C#中Invoke的用法 一

    在用.NET Framework框架的WinForm构建GUI程序界面时,如果要在控件的事件响应函数中改变控件的状态,例如:某个按钮上的文本原先叫“打开”,单击之后按钮上的文本显示“关闭”,初学者往往 ...

  7. tcmalloc asan

    http://blog.csdn.net/jinzhuojun/article/details/46659155 http://blog.csdn.net/hanlizhong85/article/d ...

  8. 解决 nfs挂载错误wrong fs type, bad option, bad superblock

    yum install nfs-utils mount -t nfs 192.168.1.153:/taimei /taimei

  9. Intellij Idea 导入多个maven项目展示在左侧栏Maven Projects

    刚刚要开始从eclipse切换成idea,据说idea功能强大,可是刚刚开始使用很多不习惯,导入第二个maven项目时之前的项目就没了,比较苦恼,下面介绍下导入多个maven项目展示在左侧栏Maven ...

  10. 1253 Dungeon Master

    题目链接: http://noi.openjudge.cn/ch0205/1253/ http://poj.org/problem?id=2251 总时间限制: 1000ms  内存限制: 65536 ...