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

分析 : 把问题抽象一下就是用编号 1 ~ n 构造一个字符串,使得字符串不包含 m 个给出的子串,且构造的代价是最小的 ( 两点间距就是代价,也就是路长 )。那如果做了很多有关在 Trie图 || AC自动机上DP的题目,那这道题就使用很套路的方法就可以了。先将给出的 m 个路线丢去构建 Trie 图,然后定义 DP[i][j] = 在编号为 i 的点 且 在 Trie 图上编号为 j 的节点状态下,最短的路径长度是多少,则可得转移方程

DP[i+1][k] = min( DP[i+1][k], DP[i][j] + GetDis(i, k) ) 且 i+1 <= k <= n (保证编号从小到大)

其中 GetDis(i, k) 是坐标点 i 和 k 的距离、而且 Trie[j].Next[k].flag == 0 即在 Trie 图上 j 状态到 k 状态合法,并不会使其包含非法路径

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<math.h>
using namespace std;
;
;
const double INF = 1e20;///不能使用 0x3f3f3f3f
int n, m;
pair<];
struct Aho{
    struct StateTable{
        int Next[Letter];
        int fail, flag;
    }Node[Max_Tot];
    int Size;
    queue<int> que;

    inline void init(){
        while(!que.empty()) que.pop();
        memset(Node[].Next, , ].Next));
        Node[].fail = Node[].flag = ;
        Size = ;
    }

    inline void insert(int *s, int len){
        ;
        ; i<len; i++){
            int idx = s[i];
            if(!Node[now].Next[idx]){
                memset(Node[Size].Next, , sizeof(Node[Size].Next));
                Node[Size].fail = Node[Size].flag = ;
                Node[now].Next[idx] = Size++;
            }
            now = Node[now].Next[idx];
        }
        Node[now].flag = ;
    }

    inline void BuildFail(){
        Node[].fail = ;
        ; i<n; i++){
            ].Next[i]){
                Node[Node[].Next[i]].fail = ;
                que.push(Node[].Next[i]);
            }].Next[i] = ;///必定指向根节点
        }
        while(!que.empty()){
            int top = que.front(); que.pop();
            Node[top].flag |= Node[Node[top].fail].flag;///注意了!!
            ; i<n; i++){
                int &v = Node[top].Next[i];
                if(v){
                    que.push(v);
                    Node[v].fail = Node[Node[top].fail].Next[i];
                }else v = Node[Node[top].fail].Next[i];
            }
        }
    }
}ac;

double GetDis(pair<int,int> &st, pair<int,int> &en)
{
    double x1 =  (double)st.first;
    double x2 =  (double)en.first;
    double y1 =  (double)st.second;
    double y2 =  (double)en.second;
    return sqrt( (double)(1.0*x1-x2)*(double)(1.0*x1-x2) +
                 (double)(1.0*y1-y2)*(double)(1.0*y1-y2));
}

][];
inline void Solve()
{

    ; i<n; i++)
        ; j<ac.Size; j++)
            dp[i][j] = INF;

    dp[][ac.Node[].Next[]] = ;
    ; i<n-; i++){
        ; j<ac.Size; j++){
            if(dp[i][j] < INF){
                ; k<n; k++){
                    int newi = k;
                    int newj = ac.Node[j].Next[k];
                    if(!ac.Node[ newj ].flag){
                        dp[newi][newj] = min(dp[newi][newj],
                                             dp[i][j]+GetDis(Point[i], Point[k]));
                    }
                }
            }
        }
    }

    double ans = INF;
    ; i<ac.Size; i++)
        ][i] < INF)
            ans = min(ans, dp[n-][i]);

    if(ans == INF) puts("Can not be reached!");
    else printf("%.2lf\n", ans);
}

int main(void)
{
    while(~scanf("%d %d", &n, &m)){
         && m==) break;
        ; i<n; i++)///这里我将编号 -1 了,也就是编号从 0 ~ n-1,所以下面操作都是按个编号来
            scanf("%d %d", &Point[i].first, &Point[i].second);
        ];
        ac.init();
        while(m--){
            int k;
            scanf("%d", &k);
            ; i<k; i++){
                scanf("%d", &tmp[i]);
                tmp[i]--;///因为编号是 0 ~ n-1
            }
            ac.insert(tmp, k);
        }ac.BuildFail();
        Solve();
    }
    ;
}

HDU 4511 小明系列故事——女友的考验 ( Trie图 && 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 小明系列故事――女友的考验(AC自己主动机+DP)

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

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

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

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

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

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

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

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

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

随机推荐

  1. cocos2dx基础篇(8) 开关按钮CCControlSwitch

    [3.x] (1)去掉 “CC” (2)对象类 CCObject 改为 Ref (3)标签类 LabelTTF 改为 Label (4)CCControlEvent 改为强枚举 Control::Ev ...

  2. Python基础语法之字典

    1 字典基础 1.1 字典是无序的对象的集合,通过键来存取,字典的键只能是不可变类型. 1.3 字典的长度可变,异构,任意嵌套. 1.2 python中不可变数据类型包括:数值类型,字符串和元组. 2 ...

  3. win10安装anaconda及tensorflow1.9版本

    前言 因为之前的anaconda的conda命令不能用,又找不到原因,所以就决定重装anaconda,然后再装个tensorflow环境.. 正文 可以去官网下载,也可以去清华的开源软件镜像站下载ht ...

  4. 配置DHCP中继

    本实验模拟企业网络场景.某公司分部的网络由交换机S1和网关路由器R1组成,员工终端PC-1和PC-2都连接在S1上.公司要求分部内所有员工主机的IP地址都通过总部的DHCP服务器自动获取.分部网关路由 ...

  5. RocketMQ高可用集群

    集群支持: RocketMQ天生对集群的支持非常友好 单Master: 优点:除了配置简单没什么优点 缺点:不可靠,该机器重启或宕机,将导致整个服务不可用 多Master: 优点:配置简单,性能最高 ...

  6. mysql数据库问题———登录进去无法操作显示You must reset your password using ALTER USER statement before executing this statement

    linux操作mysql数据库,可以登陆进去,但是操作所有命令都显示You must reset your password using ALTER USER statement before exe ...

  7. mac键盘在ubuntu下开启fn功能按键

    转载:http://wiki.ubuntu.org.cn/UbuntuHelp:AppleKeyboard Change Function Key behavior This section of t ...

  8. python字符串替换的2种方法

    python 字符串替换可以用2种方法实现:1是用字符串本身的方法.2用正则来替换字符串 下面用个例子来实验下:a = 'hello word'把a字符串里的word替换为python 1.用字符串本 ...

  9. spring cloud zuul过滤器修改requestURI 忽略大小写

    通过zuul网关处理requestURI可以做很多事情,如对uri的解密,转发,大小写转化等. 这里对URI做一个简单的大小写的转化. 写一个filter实现ZuulFilter: package c ...

  10. vue项目1-pizza点餐系统5-全局守卫

    一.导航守卫描述 当问我们点击主页.菜单等非登陆和注册按钮都会提示先登陆然后跳转到登陆界面. 1.在main.js中引入全局守卫 //全局守卫 //to是要进入那个路由,from是从那个路由出来,ne ...