BZOJ3627 [JLOI2014]路径规划

题意:求期望红绿灯时间下。途径若干加油站。经过最多若干个红绿灯,起点与终点的最短路。

思路:每一个有红绿灯的节点通过时间怎么算呢?其实t=red*red/2/(red+green),然后把这个时间附加到节点的出边上。

随后我们建立分层图,第i层表示经过了i个红绿灯时,从源点到该点的最短路径长度。

假设没有油量限制。那么我们直接跑最短路即可了。

注意到加油站非常少,于是我们枚举以每一个加油站为起点,向其它加油站经过若干个红绿灯的最短路径。

若此长度不大于最大油量,那么能够直接转移。

我们用上述信息构造新图,依然是分层图,但是每一层仅有50个点,且没有油量限制。

一次最短路出解。

Code:

#include <map>
#include <queue>
#include <string>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef double f2;
#define _abs(x) ((x)>0?

(x):-(x))

#define N 10010
int n, m, dep, lim, cost;
bool isGas[N];
f2 length[N];
map<string, int> M;
int id, S, T;

int Point_id, lab[11][N];

struct Node {
    int lab;
    f2 dis;
    Node(int _lab = 0, f2 _dis = 0):lab(_lab),dis(_dis){}
    bool operator < (const Node &B) const {
        return dis < B.dis;
    }
};
void swap(Node &x, Node &y) {
    Node tmp = x;
    x = y;
    y = tmp;
}

struct Heap {
    Node a[110010];
    int top;
    Heap():top(0){}
    void up(int x) {
        for(; x != 1; x >>= 1)
            if (a[x] < a[x >> 1])
                swap(a[x], a[x >> 1]);
            else
                break;
    }
    void down(int x) {
        int son;
        for(; (x << 1) <= top; ) {
            son=(((x<<1)==top)||(a[x<<1]<a[(x<<1)|1]))?(x<<1):((x<<1)|1);
            if (a[son] < a[x]) {
                swap(a[son], a[x]);
                x = son;
            }
            else
                break;
        }
    }
    void insert(const Node &x) {
        a[++top] = x;
        up(top);
    }
    Node Min() {
        return a[1];
    }
    void pop() {
        a[1] = a[top--];
        down(1);
    }
}H;

queue<int> q;
struct Graph {
    int head[110010], next[450010], end[450010], ind;
    f2 len[450010], dis[110010];
    bool inpath[110010];
    void reset() {
        ind = 0;
        memset(head, -1, sizeof head);
    }
    void addedge(int a, int b, f2 _len) {
        int q = ind++;
        end[q] = b;
        next[q] = head[a];
        head[a] = q;
        len[q] = _len;
    }
    void spfa(int S) {
        register int i, j;
        for(i = 1; i <= Point_id; ++i)
            dis[i] = 1e10;
        dis[S] = 0;
        memset(inpath, 0, sizeof(inpath));
        H.top = 0, H.insert(Node(S, 0));
        Node tmp;
        while(H.top) {
            tmp = Node(0, 0);
            while(H.top) {
                tmp = H.Min();
                H.pop();
                if (!inpath[tmp.lab] && _abs(tmp.dis - dis[tmp.lab]) <= 1e-6)
                    break;
            }
            if (tmp.lab == 0)
                break;
            inpath[tmp.lab] = 1;
            for(j = head[tmp.lab]; j != -1; j = next[j])
                if (dis[end[j]] > dis[tmp.lab] + len[j]) {
                    dis[end[j]] = dis[tmp.lab] + len[j];
                    H.insert(Node(end[j], dis[end[j]]));
                }
        }
    }
}G1, G2;

void Getaddedge(int a, int b, int len) {
    int j;
    if (_abs(length[b]) > 1e-7)
        for(j = 0; j < dep; ++j)
            G1.addedge(lab[j][a], lab[j + 1][b], len + length[b]);
    else
        for(j = 0; j <= dep; ++j)
            G1.addedge(lab[j][a], lab[j][b], len);
}

int Gases[101], top;

int main() {
    scanf("%d%d%d%d%d", &n, &m, &dep, &lim, &cost);

    register int i, j, k, p;
    for(i = 0; i <= dep; ++i)
        for(j = 1; j <= n; ++j)
            lab[i][j] = ++Point_id;

    string s, s1, s2;
    int red, green, num;
    for(i = 1; i <= n; ++i) {
        cin >> s >> red >> green;
        num = M[s];
        if (!num)
            M[s] = num = ++id;
        if (s == "start")
            S = num;
        else if (s == "end")
            T = num;
        else if (s.find("gas") != string::npos)
            isGas[num] = 1;
        if (red)
            length[num] = red * red / ((f2)2 * (red + green));
    }

    G1.reset();
    G2.reset();
    int a, b, len;
    for(i = 1; i <= m; ++i) {
        cin >> s1 >> s2 >> s >> len;
        a = M[s1], b = M[s2];
        Getaddedge(a, b, len);
        Getaddedge(b, a, len);
    }

    isGas[S] = isGas[T] = 1;
    for(i = 1; i <= n; ++i)
        if (isGas[i])
            Gases[++top] = i;

    for(i = 1; i <= top; ++i) {
        G1.spfa(lab[0][Gases[i]]);
        for(j = 1; j <= top; ++j) {
            if (i == j)
                continue;
            f2 add = (Gases[j] != S && Gases[j] != T) ? cost : 0;
            for(k = 0; k <= dep; ++k)
                if (G1.dis[lab[k][Gases[j]]] <= lim)
                    for(p = 0; p + k <= dep; ++p)
                        G2.addedge(lab[p][Gases[i]], lab[p + k][Gases[j]], G1.dis[lab[k][Gases[j]]] + add);
        }
    }

    G2.spfa(lab[0][S]);

    f2 res = 1e10;
    for(i = 0; i <= dep; ++i)
        res = min(res, G2.dis[lab[i][T]]);

    printf("%.3lf", res);

    return 0;
}
时间: 2024-08-04 03:35:51

BZOJ3627 [JLOI2014]路径规划的相关文章

【BZOJ-3627】路径规划 分层图 + Dijkstra + spfa

3627: [JLOI2014]路径规划 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 186  Solved: 70[Submit][Status][Discuss] Description 相信大家都用过地图上的路径规划功能,只要输入起点终点就能找出一条最优路线.现在告诉你一张地图的信息,请你找出最优路径(即最短路径).考虑到实际情况,一辆车加满油能开的时间有限,所以在地图上增加了几个加油站. 地图由点和双向边构成,每个点代表一个路口,也有可

BZOJ 3627 JLOI2014 路径规划 分层图+堆优化SPFA JLOI2014全AC达成!

题目大意:给定一个无向图,每条边有边权,有些点有点权,一些点是加油站,求一条起点到终点的最短路,使经过有点权的点不超过k次,一管油只能走limit的时间,时间到了就只能到加油站花cost的时间加油 那个红绿灯的计算公式是 red*red/2/(red+green) 考场上很多人没推出来这个挂掉了 我推出来不会写,写了爆搜,26分 限制条件有点多...考虑到k<=10,加油站<=50,我们可以对k进行分层处理,将图缩点,转化成一个在加油站之间行走的图,这样k和limit的限制条件就都解除了 首先

Unity路径规划

Unity路径规划 背景 酷跑游戏中涉及到弯道.不规则道路. 找来一些酷跑游戏的案例来看,很多都是只有直线道路,也就不存在所谓的路径问题,设置一个方向即可,本文主要给出几种我自己用过.看过的Unity中可以用做路径规划的一些资料. 方案一 Unity自带解决方案Navigation,可以参考小赵的文章: unity自带寻路Navmesh入门教程(一) unity自带寻路Navmesh入门教程(二) unity自带寻路Navmesh入门教程(三) 这几篇文章还是不错的,配合官方文档,对其功能就能就

iOS百度地图路径规划和POI检索详细总结-b

路径规划.png 百度地图的使用 百度地图API的导入网上说了许多坑,不过我遇到的比较少,这里就放两个比较常见的吧.坑一: 奥联WIFI_xcodeproj.png 如上图所示,在infoplist里加入这个字段,而且这里还可以设置提示的内容.不加的话,嘿嘿嘿,期待你的尝试.坑二:如下图 Pasted_Graphic_jpg.png 导入百度地图API运行之后报上图错误大约18到20个左右,解决方法添加libstdc++.6.0.9 的库.填完坑之后看一下我们今天要演示的效果吧. 路线规划图.g

路径规划

机器人路径规划研究综述 1.什么是路径规划 路径规划技术是机器人研究领域中的一个重要分支.所谓机器人的最优路径规划问题,就是依据某个或某些优化准则(如工作代价最小,行走路线最短,行走时间最短等),在其工作空间中找到一条从起始状态到目标状态的能避开障碍物的最优路径. 依据某种最优准则,在工作空间中寻找一条从起始状态到目标状态的避开障碍物的最优路径. 需要解决的问题: 1.始于初始点止于目标点. 2.避障. 3.尽可能优化的路径. 2.路径规划技术分类 a.静态结构化环境下的路径规划,比如说slam

基于分层路网的路径规划算法

http://www.docin.com/p-1308678703.html 路径规划一般包括如下几种情况: 最短路径规划 最短时间规划 最经济规划 通过赋予图中的边以不同的权值来满足用户不同的需求 最短路径由于普通道路限速问题,未必是最短时间到达目的地, 可能上高速更快一些 分层思想 对于一个点P,以自身为中心,不断的扩大半径进行搜索,查看当前是否包括一个升级到高层路网的节点 如果有,说明当设置P为起点,然后设置T为终点,而且当distance(pt)> R,说明应该进行路网的升层 选择一个查

ios百度地图-路径规划

百度地图的路径规划功能, 在使用百度路径的时候,出现了一些小问题,在此,分享一下自己的最简单的一个路径小demo 当然,前面的百度配置问题,我就不和大家讲了,因为这方面的资料太多了!现在,我来介绍一下这个小demo AppDelegate.m文件如下, #import "AppDelegate.h" import "rootViewController.h" @implementation AppDelegate (BOOL)application:(UIAppli

高德地图路径规划

高德地图导航sdk的路径规划获取行程信息主要用到AMapNaviManager这个类 然后调下面的方法 /*! @brief 带起点的驾车路径计算 @param startPoints 起点坐标.支持多个起点,起点列表的尾点为实际导航起点,其他坐标点为辅助信息,带有方向性,可有效避免算路到马路的另一侧. @param endPoints 终点坐标.支持多个终点,终点列表的尾点为实际导航终点,其他坐标点为辅助信息,带有方向性,可有效避免算路到马路的另一侧. @param wayPoints 途经点

PRM路径规划算法

路径规划作为机器人完成各种任务的基础,一直是研究的热点.研究人员提出了许多规划方法:如人工势场法.单元分解法.随机路标图(PRM)法.快速搜索树(RRT)法等.传统的人工势场.单元分解法需要对空间中的障碍物进行精确建模,当环境中的障碍物较为复杂时,将导致规划算法计算量较大.基于随机采样技术的PRM法可以有效解决高维空间和复杂约束中的路径规划问题. PRM是一种基于图搜索的方法,它将连续空间转换成离散空间,再利用A*等搜索算法在路线图上寻找路径,以提高搜索效率.这种方法能用相对少的随机采样点来找到