题意:从 1 走到 n,要求所走路径不能出现给定的路径,求最短路

思路:因为要求不能出现给定路径,那么我可以求助ac自动机完成判断。

我们可以在build的时候标记哪些路径不能出现,显然下面这种表示后缀不能出现,那么他也不能出现

if(node[node[u].fail].cnt && u) node[u].cnt = 1;   //都不能取

然后再把图建完整。因为如果一个路径不在Trie中有两种情况,一种是他可能是某个不能走的串的前缀,那么我就重新指向这个不能走的串,比如Trie中只有AT,那么我走ATA相当于走AT再走回A;另一种是这个路径根本没出现过,那么相当于从0开始走。

if(!node[u].next[i]){if(u == 0)node[u].next[i] = 0;elsenode[u].next[i] = node[node[u].fail].next[i];
}        

dp[i][j]表示走到i点在AC自动机上走到j点的最小路径。

代码:

#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 500 + 5;
const int M = 50 + 5;
const ull seed = 131;
const double INF = 1e20;
const int MOD = 1000000007;
double x[M], y[M];
int s[M];
double dp[M][maxn];
int m, n;
double dis(int i, int j){return sqrt((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]));
}
struct Aho{struct state{int next[M];int fail, cnt;}node[maxn];int size;queue<int> q;void init(){size = 0;newtrie();while(!q.empty()) q.pop();}int newtrie(){memset(node[size].next, 0, sizeof(node[size].next));node[size].cnt = node[size].fail = 0;return size++;}void insert(int s[], int len){int now = 0;for(int i = 0; i < len; i++){int c = s[i];if(node[now].next[c] == 0){node[now].next[c] = newtrie();}now = node[now].next[c];}node[now].cnt = 1;}void build(){node[0].fail = -1;q.push(0);while(!q.empty()){int u = q.front();q.pop();if(node[node[u].fail].cnt && u) node[u].cnt = 1;   //都不能取for(int i = 0; i <= n; i++){if(!node[u].next[i]){if(u == 0)node[u].next[i] = 0;elsenode[u].next[i] = node[node[u].fail].next[i];}else{if(u == 0) node[node[u].next[i]].fail = 0;else{int v = node[u].fail;while(v != -1){if(node[v].next[i]){node[node[u].next[i]].fail = node[v].next[i];break;}v = node[v].fail;}if(v == -1) node[node[u].next[i]].fail = 0;}q.push(node[u].next[i]);}}}}void query(){for(int i = 0; i <= n; i++){for(int j = 0; j < size; j++){dp[i][j] = INF;}}dp[1][node[0].next[1]] = 0;for(int i = 1; i <= n; i++){for(int j = 0; j < size; j++){if(dp[i][j] == INF) continue;for(int k = i + 1; k <= n; k++){if(node[node[j].next[k]].cnt) continue;dp[k][node[j].next[k]] = min(dp[k][node[j].next[k]], dp[i][j] + dis(i, k));}}}double ans = INF;for(int i = 0; i < size; i++)if(dp[n][i] < INF) ans = min(ans, dp[n][i]);if(ans == INF) printf("Can not be reached!\n");else printf("%.2f\n", ans);}}ac;
int main(){while(~scanf("%d%d", &n, &m) && n + m){for(int i = 1; i <= n; i++){scanf("%lf%lf", &x[i], &y[i]);}ac.init();while(m--){int k;scanf("%d", &k);for(int i = 0; i < k; i++){scanf("%d", &s[i]);}ac.insert(s, k);}ac.build();ac.query();}return 0;
}

转载于:https://www.cnblogs.com/KirinSB/p/11180002.html

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

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

    题目链接:点击查看 题目大意:小明在点 1 而小明的女朋友在点 n ,现在小明要去找女朋友,满足以下两个条件: 途径的序号满足严格递增 小明的女朋友给小明提出了 m 条路径是不允许走的 在满足上述两条 ...

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

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

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

    Problem Description 终于放寒假了,小明要和女朋友一起去看电影.这天,女朋友想给小明一个考验,在小明正准备出发的时候,女朋友告诉他,她在电影院等他,小明过来的路线必须满足给定的规则: ...

  4. 小明系列故事——女友的考验

    Problem Description 终于放寒假了,小明要和女朋友一起去看电影.这天,女朋友想给小明一个考验,在小明正准备出发的时候,女朋友告诉他,她在电影院等他,小明过来的路线必须满足给定的规则: ...

  5. hdu 4501 小明系列故事——买年货 多重背包

    小明系列故事--买年货                                                                          Time Limit: 500 ...

  6. hdu 4506 小明系列故事——师兄帮帮忙

    小明系列故事--师兄帮帮忙 Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other) Total ...

  7. HDU 4506 小明系列故事——师兄帮帮忙

    小明系列故事--师兄帮帮忙 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) To ...

  8. HDU 4501 小明系列故事——买年货

    小明系列故事--买年货 Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Tota ...

  9. HDU 4528 小明系列故事——捉迷藏

    题目链接~~> 做题感悟:这题需要逆向思维,先预处理一下就好. 解题思路:先预处理一下将可以看到 D 与 E 的点标记一下,这样 bfs()遍历迷宫时就可以节省很多时间,还要注意:可以重复走走过 ...

  10. hdu 4528小明系列故事——捉迷藏

    题目:点击打开链接 宽搜.注意判重.判重导致比赛的时候错了两次. #include <cmath> #include <ctime> #include <iostream ...

最新文章

  1. 我同事说我写代码像写诗
  2. 荣耀v40鸿蒙5g,荣耀V40pro再曝光,4K屏+双5000万+鸿蒙OS,再见了荣耀V30pro
  3. python-opencv怎样找到要跟踪对象的HSV
  4. ELK+Kafka集群日志分析系统
  5. upload-labs_pass10_点空点绕过_pass11_双写文件扩展名
  6. c++ cstring 转换 char_Java基本数据类型的介绍及其转换(内附字符串与多种数据之间的转换)...
  7. 关于CMS垃圾回收器的几个问题
  8. 解决复杂问题的思路 —— 从简单到复杂
  9. Boring Old Menu Bar for Mac(Big Sur菜单栏优化工具)
  10. Http请求之基于HttpUrlConnection,支持Header,Body传值,支持Multipart上传文件:
  11. NULL 与 nullptr区别与联系
  12. mysql relay_mysql relay log参数汇总
  13. c语言 猜字游戏,【c语言】       小游戏――猜字游戏
  14. Tell Me Where to Look: Guided Attention Inference Network论文翻译
  15. 再获喜讯,思迈特软件入选2021企业数智化转型升级服务全景图
  16. 2019NEFU寒假集训新生考试 2020.1.6
  17. 瑞芯微RK3328硬件设计指南
  18. c++逆天改命进阶--二叉树练习题
  19. 从街机到抓娃娃机,硬币经济也将被移动支付取代?
  20. 在Ubuntu中安装Chrome浏览器

热门文章

  1. linux新手入门学习 - linux目录结构
  2. 日常的SQL 语句使用
  3. new对象后的代码块(匿名类)
  4. 协同OA融入ERP 高端应用助企业升级转型
  5. 细说分布式Redis架构设计和那些踩过的坑
  6. Eclipse开发环境下,部署和配置svn的整个过程
  7. Mac 终端失效如何解救
  8. DataGrip 上手体验,真香!
  9. 同事1000行又臭又长 的类!被我用IDEA几分钟重构!真香!
  10. 恕我直言,你完全没有把IDEA的Diagram功能发挥出来...