HDU4511
来源:互联网 发布:sql镜像服务器 编辑:程序博客网 时间:2024/06/05 02:09
本来想水一水AC自动机的,结果调了半天才调出来QAQ。
题意大概是有n个点,求1到n的最短路,且一些路径不能作为子串出现。
解法是把约束建一个AC自动机,在自动机上DP,由于是包含某个子串即非法,so构造fail往上跳时,如果当前和目标有一个为非法,另一个也应变成非法(见下图):
这里x号节点已经是非法,所以y号节点也会变为非法,即程序中。
然后DP时用f[i][j]记录原图第i个点在自动机上第j个节点的最短路径长度,每次对于当前i,j枚举下一个可以到达的点k,j进行更新。
最后ans=min(dp[n][0..节点数])
详细见代码:
#include <cstdio>#include <algorithm>#include <string>#include <queue>#include <cmath>#include <cstring>#define maxn 550#define INF 0x7fffffffffusing namespace std;int sz,n,m,k,ch[maxn][maxn],val[maxn],fail[maxn];// AC自动机 是否可以走 string tmp;double x[maxn],y[maxn],f[maxn][maxn];// 表示第i个点在自动机第j个节点的路径长度 queue <int> q;double dis(int a,int b){ return sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));}void insert()//插入约束字符串 { int u=0,n=tmp.length(); for (int i=0;i<n;i++) { int c=tmp[i]; if (!ch[u][c]) { memset(ch[sz],0,sizeof(ch[sz])); ch[u][c]=sz; val[sz++]=0; } u=ch[u][c]; } val[u]=1;}void get_fail(){ for (int i=1;i<=n;i++) if (ch[0][i])q.push(ch[0][i]); while (!q.empty()) { int u=q.front();q.pop(); for (int i=1;i<=n;i++) if (ch[u][i]) { int k; for (k=fail[u];k&&!ch[k][i];k=fail[k]); q.push(ch[u][i]); fail[ch[u][i]]=ch[k][i]; val[ch[u][i]] | = val[ch[k][i]];//这一句很重要!很重要!!很重要!!! } else ch[u][i]=ch[fail[u]][i];//注释2:这一句等价于注释3 }}int main(){ freopen("data.out","r",stdin); freopen("wa.out","w",stdout); while (scanf("%d%d",&n,&m)) { memset(ch[0],0,sizeof(ch[0])); memset(fail,0,sizeof(fail)); sz=1; if (n==0&&m==0) break; for (int i=1;i<=n;i++) scanf("%lf%lf",&x[i],&y[i]); for (int i=1;i<=m;i++) { scanf("%d",&k); tmp=""; int p; for (int j=1;j<=k;j++) scanf("%d",&p),tmp+=p; insert(); } get_fail(); if (val[ch[0][1]])printf("Can not be reached!\n");//1作为起点不能到达无解 else { for (int i=1;i<=n;i++) for (int j=0;j<sz;j++) f[i][j]=INF; f[1][ch[0][1]]=0; for (int i=1;i<n;i++) for (int j=0;j<sz;j++) { if (f[i][j]==INF) continue; for (int k=i+1;k<=n;k++) { int jj=j; while (jj&&!ch[jj][k]) jj=fail[jj];//注释3:等价于注释2 jj=ch[jj][k]; if (!val[jj]) f[k][jj]=min(f[k][jj],f[i][j]+dis(k,i));//合法则更新 } } double ans=INF; for (int i=0;i<sz;i++)ans=min(ans,f[n][i]); if (ans==INF) printf("Can not be reached!\n"); else printf("%.2f\n",ans); } } return 0;}
0 0
- HDU4511
- HDU4511-小明系列故事――女友的考验
- hdu4511---小明系列故事——女友的考验(AC自动机+dp)
- hdu4511 小明系列故事——女友的考验(AC自动机+dp)
- 2013腾讯编程马拉松初赛第2场(3月22)(HDU 4510 HDU4511 HDU4512 HDU4513 HDU4514)
- c++火柴棒问题
- Storm教程2安装部署
- Mybatis学习总结(六).Mybatis高级查询及延迟加载
- 站在巨人的肩上——Android热更新框架Tinker探索之旅
- PX4源码分析2_QGC地面站的下载和安装
- HDU4511
- 用 Python 编写网络爬虫 笔记
- 数据结构简单选择排序
- WebService 及java网络编程等基础概念(一)
- leetcode -- 235. Lowest Common Ancestor of a Binary Search Tree【区间,二叉搜索树特点】
- decltype类型指示符
- 2392: 求各位数字之和
- VB封装DLL实例(二)
- //数学基础-推公式找规律