【最短路】【数学】CSU 1806 Toll (2016湖南省第十二届大学生计算机程序设计竞赛)
题目链接:
http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1806
题目大意:
N个点M条有向边,给一个时间T(2≤n≤10,1≤m≤n(n-1),1≤T≤104),每条边的花费是关于t的一次函数Ci*t+Di,而你能选择出发时间t(0<=t<=T),走过边视为瞬间到达,不影响t,f(t)表示在时间t开始从1出发到n的最小花费,求
题目思路:
【最短路】【数学】
这题首先有个积分符号被吓到了,但是其实不难,N才10。
很容易想到枚举t,求1到n的最短路,累加答案完/T,其实也是这么做的。那么关键就在于怎么枚举t。
当然是把一个[0,T]若干等分,求面积积分。可以用梯形公式或者simpson公式求积分。
选定一种公式,对于区间[L,R],中点Mid,如果运用公式算得ans[L,Mid]+ans[Mid,R]=ans[L,R],表示区间足够小已经没有误差,那么就可以直接得到[L,R]的答案。
否则,说明这种公式不能近似计算[L,R]的值,要把[L,R]继续细分为[L,Mid]和[Mid,R],直到区间足够小以至于没有误差。
(simpson公式的精确度为三阶,梯形公式的精确度为一阶)
1 // 2 //by coolxxx 3 //#include<bits/stdc++.h> 4 #include<iostream> 5 #include<algorithm> 6 #include<string> 7 #include<iomanip> 8 #include<map> 9 #include<stack> 10 #include<queue> 11 #include<set> 12 #include<bitset> 13 #include<memory.h> 14 #include<time.h> 15 #include<stdio.h> 16 #include<stdlib.h> 17 #include<string.h> 18 //#include<stdbool.h> 19 #include<math.h> 20 #define min(a,b) ((a)<(b)?(a):(b)) 21 #define max(a,b) ((a)>(b)?(a):(b)) 22 #define abs(a) ((a)>0?(a):(-(a))) 23 #define lowbit(a) (a&(-a)) 24 #define sqr(a) ((a)*(a)) 25 #define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b)) 26 #define mem(a,b) memset(a,b,sizeof(a)) 27 #define eps (1e-10) 28 #define J 10000 29 #define mod 1000000007 30 #define MAX 0x7f7f7f7f 31 #define PI 3.14159265358979323 32 #define N 14 33 #define M 104 34 using namespace std; 35 typedef long long LL; 36 int cas,cass; 37 int n,m,lll,ans; 38 double anss; 39 LL aans; 40 int last[N],q[N]; 41 double d[N]; 42 int c[M][2]; 43 bool u[N]; 44 struct xxx 45 { 46 int next,to; 47 }a[M]; 48 void add(int x,int y) 49 { 50 a[++lll].to=y; 51 a[lll].next=last[x]; 52 last[x]=lll; 53 } 54 double spfa(double t) 55 { 56 int i,now,to,l=0,r=1; 57 for(i=2;i<=n;i++)d[i]=MAX; 58 mem(u,0); 59 q[1]=1;d[1]=0; 60 while(l!=r) 61 { 62 now=q[l=(l+1)%N]; 63 u[now]=0; 64 for(i=last[now];i;i=a[i].next) 65 { 66 to=a[i].to; 67 if(d[to]>d[now]+c[i][0]*t+c[i][1]) 68 { 69 d[to]=d[now]+c[i][0]*t+c[i][1]; 70 if(!u[to] && to!=n) 71 { 72 u[to]=1; 73 q[r=(r+1)%N]=to; 74 } 75 } 76 } 77 } 78 return d[n]; 79 } 80 /* 81 double tixing(double l,double r) 82 { 83 return (spfa(l)+spfa(r))*(r-l)/2; 84 } 85 */ 86 double simpson(double l,double r) 87 { 88 double mid=(l+r)/2; 89 return (spfa(l)+spfa(r)+4*spfa(mid))*(r-l)/6; 90 } 91 double work(double l,double r,double epss,double c) 92 { 93 double mid=(l+r)/2,fl,fr; 94 fl=simpson(l,mid); 95 fr=simpson(mid,r); 96 // fl=tixing(l,mid); 97 // fr=tixing(mid,r); 98 if(abs(fl+fr-c)<epss)return c; 99 double x1=work(l,mid,epss/2,fl); 100 double x2=work(mid,r,epss/2,fr); 101 return x1+x2; 102 } 103 int main() 104 { 105 #ifndef ONLINE_JUDGE 106 // freopen("1.txt","r",stdin); 107 // freopen("2.txt","w",stdout); 108 #endif 109 int i,j,k; 110 int x,y,z; 111 // init(); 112 // for(scanf("%d",&cass);cass;cass--) 113 // for(scanf("%d",&cas),cass=1;cass<=cas;cass++) 114 // while(~scanf("%s",s)) 115 while(~scanf("%d",&n)) 116 { 117 anss=0;lll=0;mem(last,0); 118 scanf("%d%d",&m,&cas); 119 for(i=1;i<=m;i++) 120 { 121 scanf("%d%d%d%d",&x,&y,&c[i][0],&c[i][1]); 122 add(x,y); 123 } 124 anss=work(0,cas,1e-6,simpson(0,cas)); 125 // anss=work(0,cas,1e-6,tixing(0,cas)); 126 printf("%.12lf\n",anss/cas); 127 } 128 return 0; 129 } 130 /* 131 // 132 133 // 134 */