1806: Toll
Submit Page Summary 5 Sec 128 Mb 302 91 SpecialJudge
Description
In ICPCCamp, there are
n cities and
m unidirectional roads between cities. The
i-th road goes from the a
i-th city to the b
i-th city. For each pair of cities
u and
v, there is at most one road from
u to
v.
As traffic in ICPCCamp is becoming heavier, toll of the roads also varies. At time
t, one should pay (c
i⋅t+d
i) dollars to travel along the
i-th road.
Bobo living in the 1-st city would like to go to the n-th city. He wants to know the average money he must spend at least if he starts from city 1 at
t∈[0,T]. Note that since Bobo's car is super-fast, traveling on the roads costs him
no time.
Formally, if
f(t) is the minimum money he should pay from city 1 to city
n at time
t, Bobo would like to find
Input
The first line contains 3 integers n,m,T (2≤n≤10,1≤m≤n(n-1),1≤T≤10
4).
The i-th of the following m lines contains 4 integers a
i,b
i,c
i,d
i (1≤a
i,b
i≤n,a
i≠b
i,0≤c
i,d
i≤10
3).
It is guaranteed that Bobo is able to drive from city 1 to city n.
Output
A floating number denotes the answer. It will be considered correct if its absolute or relative error does not exceed 10
-6.
Sample Input
3 3 2
1 2 1 0
2 3 1 0
1 3 1 1
3 3 2
1 2 1 0
2 3 1 0
1 3 0 5
Sample Output
1.75000000
2.00000000
Hint
Source
最短路,但是費用随着時間而變化,問最小費用關于時間積分的平均數。
對于求積分,很早的時候大概是大一第一個學期的時候,學Python時候LWW老師就曾經給我們講過一個叫Simpson公式以及自适應Simpson公式的東西。當時呢學着覺得也沒啥用,不就是算個積分嗎,用處不大……
然後這題就是一個計算積分的題目,正好就用到了自适應Simpson公式。所謂Simpon公式,就是指對于函數f(x)在一個區間[l,r]上的積分,可以近似等于(r-l)*(f(l)+f(r)+f(mid)/6。所謂近似,就是指可以有誤差,很顯然這個誤差一般來說非常的大,是以我們要用自适應的方式。那麼什麼是自适應Simpson公式呢?其實就是說自己設定一個eps,運用二分的思想,當Simpson(l,mid)+Simpson(mid,r)與Simpson(l,r)的查大于eps的時候,自動判定為誤差過大,于是繼續把區間分細,對區間[l,mid]和[mid,r]使用自适應Simpson公式計算,然後傳回兩者之和。一直這樣遞歸下去就可以得到誤差為eps的結果。至于時間複雜度這個我真的不知道……有沒有哪位dalao能告訴我。具體見代碼:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#define eps 1e-8
#define N 100
using namespace std;
typedef pair<double,int> P;
struct Edge{int y,c,d;};
vector<Edge> g[N];
const int INF=1e9;
double d[N];
int m,n,T;
inline double dijkstra(double t)
{
priority_queue<P,vector<P>,greater<P> > q;
for(int i=1;i<=n;i++) d[i]=INF;
d[1]=0; q.push(P(0,1));
while (!q.empty())
{
int j=q.top().second;
double w=q.top().first;
q.pop(); if (w-d[j]>eps) continue;
for(int k=0;k<g[j].size();k++)
{
int y=g[j][k].y;
double dist=w+g[j][k].c*t+g[j][k].d;
if (d[y]-dist>eps) {d[y]=dist; q.push(P(d[y],y));}
}
}
return d[n];
}
double simpson(double l,double r)
{
double mid=(l+r)/2.0;
return (r-l)*(dijkstra(l)+dijkstra(r)+4*dijkstra(mid))/6.0;
}
double rsimpson(double l,double r)
{
double mid=(l+r)/2.0;
double A=simpson(l,r);
double L=simpson(l,mid);
double R=simpson(mid,r);
if (fabs(A-L-R)>=eps) return rsimpson(l,mid)+rsimpson(mid,r);
else return A;
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&T))
{
memset(g,0,sizeof(g));
for(int i=1;i<=m;i++)
{
int u,v,x,y;
scanf("%d%d%d%d",&u,&v,&x,&y);
g[u].push_back(Edge{v,x,y});
}
printf("%.7f\n",(double)rsimpson(0,T)/T);
}
return 0;
}