CSU1806-Toll(Simpson积分)

63 篇文章 0 订阅
17 篇文章 0 订阅

1806: Toll

            Time Limit: 5 Sec       Memory Limit: 128 Mb       Submitted: 266       Solved: 82       SpecialJudge

Description

 In ICPCCamp, there are  cities and  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  uand  v, there is at most one road from  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  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

湖南省第十二届大学生计算机程序设计竞赛

题意:城市之间有n个城市和m个单向道路。 第i条路从城市a[i]到城市b[i]。 对于每对城市u和v,最多有一条从u到v的道路。随着交通量越来越大,道路的费用也有所不同。 在时间t,应该支付(ci⋅t+ di)美元以沿着第i条路行驶。一个在一号城市的人想去第n个城市。 他想知道他必须花费的平均金额,他从t∈[0,T]的城市1开始。因为车速是超快的,通过道路不会花费时间。f(t)是他在时间t从城市1到城市n应该支付的最小钱

解题思路:最短路,自适应Simpson积分。

有这样一个积分公式:这个东西用于计算不方便直接积分的时候的近似积分。

由于直接套公式会与实际有很大偏差,有一个改进:

要求[L,R]的积分,先令m=(L+R)/2,根据上面的公式,求出[L,R]的公式值s0,以及[L,m]的公式值s1[m,R]的公式值s2

如果s0 s1+s2 很接近,那么可以认为[L,R]的积分就是s0;否则进行递归,分别求[L,m]的积分和[m,R]的积分。


#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
#include <vector>
#include <set>
#include <bitset>
#include <stack>
#include <map>
#include <climits>
#include <functional>

using namespace std;

#define LL long long
const int INF=0x3f3f3f3f;
const double eps=1e-8;

int n,m,t;
int s[20],nt[200],e[200],c[200],d[200],cnt;
int visit[20];
double dis[20];

double SPFA(double x)
{
    for(int i=0;i<=n;i++) dis[i]=1.0*INF;
    memset(visit,0,sizeof visit);
    queue<int>q;
    visit[1]=1;
    q.push(1);
    dis[1]=0;
    while(!q.empty())
    {
        int pre=q.front();
        q.pop();
        visit[pre]=0;
        for(int i=s[pre];~i;i=nt[i])
        {
            if(dis[pre]+c[i]*x+d[i]<dis[e[i]])
            {
                dis[e[i]]=dis[pre]+c[i]*x+d[i];
                if(!visit[e[i]])
                {
                    visit[e[i]]=1;
                    q.push(e[i]);
                }
            }
        }
    }
    return dis[n];
}

double get(double L,double R)
{
    return (R-L)*(SPFA(L)+4*SPFA((L+R)/2)+SPFA(R))/6;
}

double Ans(double L,double R)
{
    double mid=(L+R)/2;
    double s0=get(L,R),s1=get(L,mid),s2=get(mid,R);
    if(fabs(s0-(s1+s2))<=eps) return s0;
    else return Ans(L,mid)+Ans(mid,R);
}

int main()
{
    while(~scanf("%d%d%d",&n,&m,&t))
    {
        memset(s,-1,sizeof s);
        cnt=1;
        for(int i=1;i<=m;i++)
        {
            int u,v,cc,dd;
            scanf("%d%d%d%d",&u,&v,&cc,&dd);
            nt[cnt]=s[u],e[cnt]=v,c[cnt]=cc,d[cnt]=dd,s[u]=cnt++;
        }
        printf("%.8lf\n",Ans(0,1.0*t)/t);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值