zoukankan      html  css  js  c++  java
  • bzoj3627: [JLOI2014]路径规划

    Description

    相信大家都用过地图上的路径规划功能,只要输入起点终点就能找出一条最优路线。现在告诉你一张地图的信息,请你找出最优路径(即最短路径)。考虑到实际情况,一辆车加满油能开的时间有限,所以在地图上增加了几个加油站。

    地图由点和双向边构成,每个点代表一个路口,也有可能是加油站或起点终点。有些路口还装有红绿灯。由于经过太多的红绿灯会让人感到不爽,所以请求在经过不超过k个红绿灯的情况下,最少平均花费多少时间能从起点到终点。保证起点终点和加油站没有红绿灯。

    (题目不考虑最坏情况下能否加到油,只考虑平均花费时间的前提下,车能否到达加油站加油)。

    Input

    第一行输入5个整数n,m,k,limit,cost,表示有n个点m条边,车能开limit长的时间,及加油所花时间cost。

    接下来n行输入每个点信息,包括点的名称(带“gas”的为加油站,“start”为起点,“end”为终点),及该点是否有红绿灯,(a,b表示)(若为a=0则表示没有,a表示红灯长,b表示绿灯长)。

    接下来m行输入每条边信息,包括边的起点,终点,边的名称,通过该边所花时长。

    保证点和边名的长度不大于20,只有大小写字母,数字及‘_’组成。

    Output

    一行输出最少平均花费时长。

    Sample Input

    5 8 1 100 10
    start 0 0
    azhan 10 10
    xxgasxx 0 5
    bpoint 20 5
    end 0 100
    start azhan sdf 30
    azhan xxgasxx ewfg 20
    start end r3tg 200
    end azhan 1xq2 70
    azhan bpoint gg 10
    xxgasxx bpoint kk 30
    bpoint end dsg 40
    xxgasxx end t_s 100
    

    Sample Output

    162.500
    

    HINT

    共14组数据:

    其中3组数据,满足n<10,m<20,k<5

    另有组没有红绿灯

    所有数据满足n<=10000,m<=20000,k<=10,加油站<=50

    答案保留3位小数

    题解

    等红绿灯所花费时间的期望为(frac{a^2}{2(a+b)}),这个可以用积分积出来。具体的,我们假设一个长度为(a+b)的周期中红灯的出现时间为([0,a])这一区间,我们在(x)时刻到达的概率是(frac{1}{a+b}),等待的时间期望为(frac{a-x}{a+b})。那么总的期望就是

    [int _0^afrac{a-x}{a+b}mathrm{d}x=frac{a^2}{2(a+b)} ]

    由于加油站很少,我们考虑预处理出从每个加油站出发能到达哪些加油站。注意,这里我们将起点和终点也视作加油站。那么这就是一个分层图问题,我们设(d[i][j])表示经过了(i)个红绿灯到达(j)的最短路,这个东西可以用(SPFA)轻松求出。

    现在我们已经知道了每个加油站可以到哪些加油站以及中间需要经过的红绿灯数,那么其余的不是加油站的点都已经没有用了。我们可以建一张新图,只保留加油站,得到的仍是分层图。然后再在新图上跑一边(SPFA)即可得到答案。

    代码

    #include<bits/stdc++.h>
    #define MAXN 20010
    #define INF 0x3f3f3f3f
    #define fir first
    #define sec second
    #define mkp make_pair
    using namespace std;
    typedef pair<int, int> pa;
    double d[15][MAXN];
    bool vis[15][MAXN];
    map<string, int> ma;
    struct Point {
    	int r, g; double w;
    }p[MAXN];
    struct Edge {
    	int t, next; double v;
    }e[MAXN << 1];
    struct New {
    	int t, next, w; double v;
    }g[MAXN << 1];
    int hd1[MAXN], cnt1, hd2[MAXN], cnt2, N, M, K, L, C, gas[MAXN], tot;
    inline void Add_Edge(int from, int to, double v) {
    	e[++cnt1].t = to; e[cnt1].next = hd1[from]; hd1[from] = cnt1; e[cnt1].v = v;
    }
    inline void Add_New(int from, int to, double v, int w) {
    	g[++cnt2].t = to; g[cnt2].next = hd2[from]; hd2[from] = cnt2; g[cnt2].v = v; g[cnt2].w = w;
    }
    queue< pa >q;
    inline void Spfa1(int S) {
    	memset(vis, 0, sizeof(vis));
    	memset(d, 0x7f, sizeof(d));
    	d[0][S] = 0; q.push(mkp(S, 0)); vis[0][S] = 1;
    	while (!q.empty()) {
    		int u = q.front().fir, x = q.front().sec; q.pop(); vis[x][u] = 0;
    		for (int i = hd1[u]; i; i = e[i].next) {
    			int v = e[i].t, y = p[v].r ? x + 1 : x;
    			double dis = e[i].v + p[v].w + d[x][u];
    			if (dis <= L && dis<d[y][v] && y <= K) {
    				d[y][v] = dis;
    				if (!vis[y][v])vis[y][v] = 1, q.push(mkp(v, y));
    			}
    		}
    	}
    }
    inline void Spfa2(int S) {
    	memset(vis, 0, sizeof(vis));
    	memset(d, 0x7f, sizeof(d));
    	d[0][S] = 0; q.push(mkp(S, 0)); vis[0][S] = 1;
    	while (!q.empty()) {
    		int u = q.front().fir, x = q.front().sec; q.pop(); vis[x][u] = 0;
    		for (int i = hd2[u]; i; i = g[i].next) {
    			int v = g[i].t, y = x + g[i].w;
    			if (y>K)continue;
    			double dis = g[i].v + C + d[x][u];
    			if (dis<d[y][v]) {
    				d[y][v] = dis;
    				if (!vis[y][v])vis[y][v] = 1, q.push(mkp(v, y));
    			}
    		}
    	}
    }
    string s, s1, s2;
    int S, T, x, y;
    int main() {
    #ifndef ONLINE_JUDGE
    	freopen("pathplan.in", "r", stdin);
    	freopen("pathplan.out", "w", stdout);
    #endif
    	scanf("%d%d%d%d%d", &N, &M, &K,&L, &C);
    	for (int i = 1; i <= N; i++) {
    		cin >> s; scanf("%d%d", &p[i].r, &p[i].g);
    		ma[s] = i;
    		if (s.find("gas") != string::npos)gas[++tot] = i;
    		if (!s.compare("start"))S = i, gas[++tot] = i;
    		if (!s.compare("end"))T = i, gas[++tot] = i;
    		if (p[i].r)p[i].w = (double)p[i].r*p[i].r*0.5 / (p[i].r + p[i].g);
    	}
    	for (int i = 1; i <= M; i++) {
    		cin >> s >> s1 >> s2; scanf("%d", &x);
    		Add_Edge(ma[s], ma[s1], x); Add_Edge(ma[s1], ma[s], x);
    	}
    	for (int i = 1; i <= tot; i++) {
    		Spfa1(gas[i]);
    		for (int j = 1; j <= tot; j++) {
    			if (j == i)continue;
    			for (int k = 0; k <= K; k++) {
    				if (d[k][gas[j]] != INF)Add_New(gas[i], gas[j], d[k][gas[j]], k);
    			}
    		}
    	}
    	Spfa2(S);
    	double ans = INF;
    	for (int i = 0; i <= K; i++)ans = min(ans, d[i][T]);
    	printf("%.3lf", ans - C);
    	return 0;
    }
    
  • 相关阅读:
    JS实现AES加密并与PHP互通的方法分析
    Microsoft: Get started with Dynamic Data Masking in SQL Server 2016 and Azure SQL
    使用php完成常见的文件上传功能
    从php到浏览器的缓存机制
    Hibernate的映射机制是怎样?
    自定义可视化调试工具(Microsoft.VisualStudio.DebuggerVisualizers)
    自适应大小事件
    flex Chrome flash调试时 出现Shockwave flash has crashed的解决办法
    [ActionScript 3] 本地安全沙箱问题最快解决方法
    在C#中调用VBScript和JavaScript等脚本的实现
  • 原文地址:https://www.cnblogs.com/lrj998244353/p/8809920.html
Copyright © 2011-2022 走看看