HDU 4511 (AC自动机 DP)
2016-06-17 18:12
316 查看
题目链接:点击这里
题意:给定n个点的坐标, 每次只能从一个点走到编号比他大的点. 求一条最短的路径, 并且这条路径上不能有给出的子路径.
把这些子路径插进AC自动机里, 然后用dp[i][j]表示在图上的i, 字典树上的j的最短路径, 转移方程就是dp[i][j]=min{dp[p[k]+dis(p,i)∣∣next[k][i]=j}
#include <bits/stdc++.h> using namespace std; #define maxn 505 #define INF 1e20 int n, m, k; int buf[maxn]; double p[maxn][2]; double dis (int i, int j) { double x = p[i][0]-p[j][0], y = p[i][1]-p[j][1]; return sqrt (x*x + y*y); } struct trie { int next[maxn][55], fail[maxn], end[maxn]; int root, cnt; int new_node () { memset (next[cnt], -1, sizeof next[cnt]); end[cnt++] = 0; return cnt-1; } void init () { cnt = 0; root = new_node (); } 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] = new_node (); } now = next[now][id]; } end[now]++; } void build () {//构建fail指针 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]); } } } } double dp[55][maxn];//在字典树上i 图上的j void query () { for (int i = 1; i <= n; i++) { for (int j = 0; j < cnt; j++) { dp[i][j] = INF; } } dp[1][next[root][1]] = 0; for (int i = 1; i < n; i++) { for (int j = 0; j < cnt; j++) { if (end[j] || dp[i][j] >= INF) continue; for (int x = i+1; x <= n; x++) { int nexti = next[j][x]; if (end[nexti]) continue; dp[x][nexti] = min (dp[x][nexti], dp[i][j] + dis (i, x)); } } } double ans = INF; for (int i = 0; i < cnt; i++) ans = min (ans, dp [i]); if (ans == INF) { printf ("Can not be reached!\n"); } else printf ("%.2f\n", ans); } }ac; int main () { //freopen ("in.txt", "r", stdin); while (cin >> n >> m && n+m) { for (int i = 1; i <= n; i++) { cin >> p[i][0] >> p[i][1]; } ac.init (); for (int i = 0; i < m; i++) { cin >> k; for (int j = 0; j < k; j++) { cin >> buf[j]; } ac.insert (buf, k); } ac.build (); ac.query (); } return 0; }
相关文章推荐
- maven学习篇(三)---Maven生命周期详解
- 用websocket实现后台推送消息
- 学习如何看懂SQL Server执行计划(一)——数据查询篇
- Android AsyncTask 源码解析
- c++——第一次作业2
- 第16周-阅读程序2(2)
- nginx 代理https后,spring mvc web应用redirect https变成http
- Clever Y [Bzoj 1467]
- 飛飛(七十四)阅读 STL中的简单容器和迭代器
- memset效率问题
- TCP/IP 封装-分用
- 基于bootstrap风格的项目
- Android studio 和 Eclipse在Win上常见快捷键对比
- Xdebug文档(六) 分析PHP脚本
- android 设置跳转
- 纯代码实现 AutoLayout
- find命令的使用
- Socket与SocketServer结合多线程实现多客户端与服务器通信
- python IDLE 背景以及字体的修改
- 【solr】关于solr schema.xml 和solrconfig.xml的解释