【最短路】【数学】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
",anss/cas);
127     }
128     return 0;
129 }
130 /*
131 //
132 
133 //
134 */
View Code
原文地址:https://www.cnblogs.com/Coolxxx/p/5849807.html