博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU 4511 (AC自动机+状态压缩DP)
阅读量:6236 次
发布时间:2019-06-22

本文共 2510 字,大约阅读时间需要 8 分钟。

题目链接:  

题目大意:从1走到N,中间可以选择性经过某些点,比如1->N,或1->2->N,但是某些段路径(注意不是某些条)是被禁止的。问从1->N的最短距离。

解题思路

AC自动机部分:

如果只是禁掉某些边,最短路算法加提前标记被禁的边即可。

但是本题是禁掉指定的路段,所以得边走边禁,需要一个在线算法。

所以使用AC自动机来压缩路段,如禁掉的路段是1->2->3,那么insert字符串(123) ,注意点只有1~50,所以0~50用ASCII 压缩成字符串即可。

这样就能够完成禁止路段的在线状态转移。

 

状态压缩DP部分:

其实就是手艹一个两点之间的最短路。dp[i][j]表示在地点i,当前字符是j的状态。

初始化:fill(&dp0][0],&dp[maxn-1][maxp-1],inf),inf=1e12,double的inf很头疼,memset是不能用的。

边界:首先找下出发点在pool中的位置,s=root->next[0],如果s被禁,那么就不用算了。否则dp[0][s]=0;

方程:  dp[k][t]=min(dp[k][t],dp[i][j]+dist(i,k))

答案:min(dp[n-1][0..cnt])

解释下方程,其中for(0...i...n-1),for(i+1...k....n) ,枚举两个点。

然后就是中间多出的AC自动机的状态压缩for(0....j....cnt),负责打出所有的路径转移状态。

 

#include "cstdio"#include "cstring"#include "string"#include "iostream"#include "queue"#include "math.h"using namespace std;#define maxn 55#define maxp 10*100#define inf 1e12struct Point{    double x,y;}P[maxn];struct Trie{    Trie *next[maxn],*fail;    int cnt;}pool[maxp],*root,*sz;int pre,now;double dp[55][maxp];Trie *newnode(){    Trie *ret=sz++;    memset(ret->next,0,sizeof(ret->next));    ret->fail=0;    ret->cnt=0;    return ret;}void init(){    sz=pool;    root=newnode();}void Insert(string str){    Trie *pos=root;    for(int i=0;i
next[c]) pos->next[c]=newnode(); pos=pos->next[c]; } pos->cnt++;}void getfail(){ queue
Q; for(int c=0;c
next[c]) { root->next[c]->fail=root; Q.push(root->next[c]); } else root->next[c]=root; } while(!Q.empty()) { Trie *x=Q.front();Q.pop(); for(int c=0;c
next[c]) { x->next[c]->fail=x->fail->next[c]; x->next[c]->cnt+=x->fail->next[c]->cnt; Q.push(x->next[c]); } else x->next[c]=x->fail->next[c]; } }}double dist(Point a,Point b) {
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}int main(){ //freopen("in.txt","r",stdin); int n,m,k,p; while(scanf("%d%d",&n,&m)!=EOF&&n) { init(); for(int i=0;i
next[0]-pool; if(root->next[0]->cnt) printf("Can not be reached!\n"); else { int cnt=sz-pool; fill(&dp[0][0],&dp[54][maxp-1],inf); dp[0][s]=0; for(int i=0; i
next[k]->cnt) continue; int t=pos->next[k]-pool; dp[k][t]=min(dp[k][t],dp[i][j]+dist(P[i],P[k])); } } } double ans=inf; for(int i=0; i

 

11848330 2014-10-11 14:48:53 Accepted 109MS 748K 2865B C++

转载地址:http://eazia.baihongyu.com/

你可能感兴趣的文章
特斯拉Model 3成为核心产品 生产线问题刚好又坏在运输环节 ...
查看>>
如何在Windows系统下的Eclipse中安装Cloud Toolkit
查看>>
阿里云服务器实例规格族配置怎么选?
查看>>
关于K8s集群器日志收集的总结
查看>>
Java中String和StringBuffer对于拼接运算中效率的对比 ...
查看>>
吉利自动驾驶之路将完成:到2022年推出L5级别亚运园区接驳车 ...
查看>>
阿里重磅开源首款自研科学计算引擎Mars,揭秘超大规模科学计算 ...
查看>>
java B2B2C 源码 多级分销Springcloud多租户电子商城系统-使用spring cloud Bus刷新配置...
查看>>
Ionic如何创建自定义展开标题组件
查看>>
用AI简化医疗重复性任务,这家美国创企这样做
查看>>
商用车诊修服务商“瑞修得”获1500万元Pre-A轮融资
查看>>
过滤器实栗 登录检测
查看>>
javaUtil类
查看>>
阿里云轻量应用服务器怎么绑定域名?
查看>>
HTML+CSS静态博客
查看>>
分布式熔断、限流与服务保护:深入 Hystrix 原理及使用
查看>>
简短而有效的python queue队列解释
查看>>
深度解析大快DKadoop大数据运维管理平台功能
查看>>
java短信接口-单条短信接口
查看>>
Confluence 6 示例 - https://confluence.atlassian.com/
查看>>