【图】速度限制

问题 I: 【图】速度限制

时间限制: 1 Sec   内存限制: 128 MB
提交: 6   解决: 2
[ 提交][ 状态][ 讨论版][命题人: admin]

题目描述

在这个繁忙的社会中,我们往往不再去选择最短的道路,而是选择最快的路线。开车时每条道路的限速成为最关键的问题。不幸的是,有一些限速的标志丢失了,因此你无法得知应该开多快。一种可以辩解的解决方案是,按照原来的速度行驶。你的任务是计算两地间的最快路线。

你将获得一份现代化城市的道路交通信息。为了使问题简化,地图只包括路口和道路。每条道路是有向的,只连接了两条道路,并且最多只有一块限速标志,位于路的起点。两地A和B,最多只有一条道路从A连接到B。你可以假设加速能够在瞬间完成并且不会有交通堵塞等情况影响你。当然,你的车速不能超过当前的速度限制。

输入

第一行是3个整数N,M和D(2<=N<=150),表示道路的数目,用0..N-1标记。M是道路的总数,D表示你的目的地。接下来的M行,每行描述一条道路,每行有4个整数A(0≤A<N),B(0≤B<N),V(0≤V≤500)and L(1≤L≤500),这条路是从A到B的,速度限制是V,长度为L。如果V是0,表示这条路的限速未知。如果V不为0,则经过该路的时间T=L/V。否则T=L/Vold,Vold是你到达该路口前的速度。开始时你位于0点,并且速度为70。

输出

仅一行整数,表示从0到D经过的城市。
输出的顺序必须按照你经过这些城市的顺序,以0开始,以D结束。仅有一条最快路线。

样例输入

6 15 1
0 1 25 68
0 2 30 50
0 5 0 101
1 2 70 77
1 3 35 42
2 0 0 22
2 1 40 86
2 3 0 23
2 4 45 40
3 1 64 14
3 5 0 23
4 1 95 8
5 1 0 84
5 2 90 64
5 3 36 40

样例输出

0 5 2 3 1


最开始使用dfs,TLE,然后使用了最普通的dijkstra...

    void dijkstra(){
        priority_queue<node>ss;
        ss.push(node(0,0,70));
        dis[0] = .0;
        while (!ss.empty()){
            auto tmp = ss.top();
            ss.pop();
            int u = tmp.second,tev;
            int node_v = tmp.last;
            double t = tmp.first,tet;
            for(int i = 0 ;i < map[u].size() ; ++i){
                tev = map[u][i].ve? map[u][i].ve:node_v;
                tet = map[u][i].len*1.0/tev;
                if(dis[map[u][i].to]>t+tet){
                    dis[map[u][i].to]=t+tet;
                    store[map[u][i].to] = u;
                    ss.push(node(dis[map[u][i].to],map[u][i].to,tev));
                }
            }
        }
    }

毫无疑问这个也行不通,贪心的思想只适用于前项选择对后项不会影响的结果,在这个版本的dijkstra中,dis[to]>dis[from]+d进行更新时忽略了当前速度造成的影响,只把时间作为更新的标准是错误的...


所以,姑且参考了大神的代码...

发现dijkstra还可以这么玩

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <deque>
#include <cmath>
using namespace std;
const int N = 155;
const int inf = 0x3f3f3f3f;

class node{
public:
    double first;///通过点prev到达点second所需的时间
    int second;
    int prev;   
    int last;   ///通过点prev到达点second的速度
    node(double k,int p,int s,int v):first(k),prev(p),second(s),last(v){}
    bool operator<(const node&X)const{
        return first>X.first;
    }
};
class graphic{
public:
    void init(){
        int m;
        int f,t,v,l;
        cin>>n>>m>>tar;
        for(int i = 0 ; i < m ; ++i){
            scanf("%d %d %d %d",&f,&t,&v,&l);
            map[f].emplace_back(e(t,v,l));
        }
        for(int i = 0 ; i <= n ; ++i) {
            store[i] = i;
            for(int j = 0 ; j <= n ; ++j) {
                pre[i][j] = -1;
                dis[i][j] = 1e9;
            }
        }
    }
    void out_ans(int prev,int now){
        if(pre[prev][now]==-1){
            printf("%d ",now);
            return;
        }
        else{
            out_ans(pre[prev][now],prev);
            printf(now!=tar?"%d ":"%d\n",now);
        }
    }
    void deal(){
        res = 1e9;
        dijkstra();
        int pos = tar;
        for(int i = 0 ; i < n ; ++i){
            if(dis[i][tar]<dis[pos][tar])pos = i;
        }
        out_ans(pos,tar);
    }
private:
    double res;
    int tar,n;
    struct e{
        int to,ve,len;
        e(int a,int b,int c):to(a),ve(b),len(c){}
    };
    vector<e>map[N];
    int store[N];
    double dis[N][N];
    int pre[N][N];
    void dijkstra(){
        priority_queue<node>ss;
        ss.push(node(0,0,0,70));
        dis[0][0] = .0;
        while (!ss.empty()){
            auto tmp = ss.top();
            ss.pop();
            int la = tmp.prev,u = tmp.second,tev;
            int node_v = tmp.last;
            for(int i = 0 ;i < map[u].size() ; ++i){
                tev = map[u][i].ve? map[u][i].ve:node_v;
                double t = dis[la][u],tet;
                tet = 1.0*map[u][i].len/tev;
                if(t+tet<dis[u][map[u][i].to]){
                    dis[u][map[u][i].to] = t+tet;
                    pre[u][map[u][i].to] = la;
                    ss.push(node(dis[u][map[u][i].to],u,map[u][i].to,tev));
                }
            }
        }
    }
};
graphic ss;
int main(){
    ss.init();
    ss.deal();
}
     Language: C++
     Result: 正确
     Time:84 ms
     Memory:3596 kb


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值