问题 I: 【图】速度限制
时间限制: 1 Sec 内存限制: 128 MB提交: 6 解决: 2
[ 提交][ 状态][ 讨论版][命题人: admin]
题目描述
在这个繁忙的社会中,我们往往不再去选择最短的道路,而是选择最快的路线。开车时每条道路的限速成为最关键的问题。不幸的是,有一些限速的标志丢失了,因此你无法得知应该开多快。一种可以辩解的解决方案是,按照原来的速度行驶。你的任务是计算两地间的最快路线。
你将获得一份现代化城市的道路交通信息。为了使问题简化,地图只包括路口和道路。每条道路是有向的,只连接了两条道路,并且最多只有一块限速标志,位于路的起点。两地A和B,最多只有一条道路从A连接到B。你可以假设加速能够在瞬间完成并且不会有交通堵塞等情况影响你。当然,你的车速不能超过当前的速度限制。
你将获得一份现代化城市的道路交通信息。为了使问题简化,地图只包括路口和道路。每条道路是有向的,只连接了两条道路,并且最多只有一块限速标志,位于路的起点。两地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结束。仅有一条最快路线。
输出的顺序必须按照你经过这些城市的顺序,以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