题目:Toll
传送门:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1806
题目简述:给定n个点m条有向边的有向图,每条边的花费是$b_i * t +d_i$,设f(t)表示给定t的时候1-n的最小花费,求:${\frac{\int_0^T{f(t)dt}}{T}}$
分析:
(1)f(t)可用最短路求出来。
(2)积分值可用自适应辛普森积分法计算。
注意:有向图!
代码:
#include <cstdio> #include <cstring> const int N=17,QN=17,M=207; const double EPS=1e-15,INF=1e9; int n,m; int size,fi[N]; struct Edge{int to,next;double c,d;}e[M]; void Gadd(int x,int y,double c,double d){ e[++size].to=y;e[size].c=c;e[size].d=d;e[size].next=fi[x];fi[x]=size; } int q[N+10];double dis[N];bool use[N]; double F(double x){ for(int i=2;i<=n;++i)dis[i]=INF; int h=0,t=1;dis[q[t]=1]=0; for(int v;h!=t;){ if((++h)==QN)h=0;use[v=q[h]]=false; for(int i=fi[v],u;i;i=e[i].next){ u=e[i].to; if(dis[v]+e[i].c*x+e[i].d<dis[u]){ dis[u]=dis[v]+e[i].c*x+e[i].d; if(use[u])continue; if((++t)==QN)t=0;use[q[t]=u]=true; } } } return dis[n]; } double Simpson(double l,double r){ return (r-l)*(F(l)+4*F((l+r)/2)+F(r))/6; } double Abs(double x){return x<0?-x:x;} double Integral(double l,double r,double S){ double mid=(l+r)/2; double A=Simpson(l,mid); double B=Simpson(mid,r); if(Abs(A+B-S)<EPS) return S;else return Integral(l,mid,A)+Integral(mid,r,B); } int main(){ for(double T,ans;~scanf("%d%d%lf",&n,&m,&T);){ size=0;memset(fi,0,sizeof fi); for(int i=1,a,b,c,d;i<=m;++i){ scanf("%d%d%d%d",&a,&b,&c,&d); Gadd(a,b,(double)c,(double)d); } ans=Integral(0,T,Simpson(0,T))/T; printf("%.8f\n",ans); } return 0; }
时间: 2024-10-25 20:00:52