CSU 1806 Toll

最短路,自适应$Simpson$积分。

看了别人的题解才知道有个东西叫自适应$Simpson$积分。

有这样一个积分公式:$\int_a^b {f(x)dx}  \approx \frac{{b - a}}{6}\left[ {f(a) + 4f\left( {\frac{{a + b}}{2}} \right) + f(b)} \right]$。这个东西用于计算不方便直接积分的时候的近似积分。

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

要求$[L,R]$的积分,先令$m = \frac{{L + R}}{2}$,根据上面的公式,求出$[L,R]$的公式值${s_0}$,以及$[L,m]$的公式值${s_1}$,$[m,R]$的公式值${s_2}$。

如果${s_0}$与${s_1} + {s_2}$很接近,那么可以认为$[L,R]$的积分就是${s_0}$;否则进行递归,分别求$[L,m]$的积分和$[m,R]$的积分。

知道了这个东西之后,这题就变成水题了......

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0),eps=1e-8;
void File()
{
    freopen("D:\\in.txt","r",stdin);
    freopen("D:\\out.txt","w",stdout);
}
template <class T>
inline void read(T &x)
{
    char c = getchar(); x = 0;while(!isdigit(c)) c = getchar();
    while(isdigit(c)) { x = x * 10 + c - ‘0‘; c = getchar();  }
}

int n,m,T;
struct Edge{int u,v,c,d,nx;}e[200];
int h[20],sz;

void add(int u,int v,int c,int d)
{
    e[sz].u=u; e[sz].v=v; e[sz].c=c; e[sz].d=d;
    e[sz].nx=h[u]; h[u]=sz++;
}

double SPFA(double x)
{
    double dis[20]; bool flag[20];
    for(int i=1;i<=n;i++) dis[i]=999999999999.0;
    memset(flag,0,sizeof flag);
    queue<int>Q; flag[1]=1; Q.push(1); dis[1]=0;
    while(!Q.empty())
    {
        int top=Q.front(); Q.pop(); flag[top]=0;
        for(int i=h[top];i!=-1;i=e[i].nx)
        {
            if(dis[top]+e[i].c*x+e[i].d<dis[e[i].v])
            {
                dis[e[i].v]=dis[top]+e[i].c*x+e[i].d;
                if(flag[e[i].v]==0)
                {
                    flag[e[i].v]=1;
                    Q.push(e[i].v);
                }
            }
        }
    }
    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 m=(L+R)/2;
    double s0,s1,s2;
    s0=get(L,R); s1=get(L,m); s2=get(m,R);
    if(fabs(s0-(s1+s2))<=eps) return s0;
    else return Ans(L,m)+Ans(m,R);
}

int main()
{
    while(~scanf("%d%d%d",&n,&m,&T))
    {
        memset(h,-1,sizeof h); sz=0;
        for(int i=1;i<=m;i++)
        {
            int u,v,c,d; scanf("%d%d%d%d",&u,&v,&c,&d);
            add(u,v,c,d);
        }
        printf("%.8lf\n",Ans(0,1.0*T)/T);
    }
    return 0;
}
时间: 2024-11-06 10:23:04

CSU 1806 Toll的相关文章

[CSU1806]Toll

题目: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 <

CSU 1804: 有向无环图(拓扑排序)

http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1804 题意:…… 思路:对于某条路径,在遍历到某个点的时候,之前遍历过的点都可以到达它,因此在这个时候对答案的贡献就是∑(a1 + a2 + a3 + ... + ai) * bv,其中a是之前遍历到的点,v是当前遍历的点. 这样想之后就很简单了.类似于前缀和,每次遍历到一个v点,就把a[u]加给a[v],然后像平时的拓扑排序做就行了. 1 #include <bits/stdc++.h>

CSU 1111: 三家人【有趣的思维题】

1111: 三家人 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 2241  Solved: 874 [Submit][Status][Web Board] Description 有三户人家共拥有一座花园,每户人家的太太均需帮忙整理花园.A 太太工作了5 天,B 太太则工作了4 天,才将花园整理完毕.C 太太因为正身怀六甲无法加入她们的行列,便出了90元.请问这笔钱如何分给A.B 二位太太较为恰当?A 应得多少元?90/(5+4)*5=$50

CSU 1112: 机器人的指令【模拟题】

1112: 机器人的指令 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 1858  Solved: 682 [Submit][Status][Web Board] Description 数轴原点有一个机器人.该机器人将执行一系列指令,你的任务是预测所有指令执行完毕之后它的位置. ·LEFT:往左移动一个单位 ·RIGHT: 往右移动一个单位 ·SAME AS i: 和第i 条执行相同的动作.输入保证i 是一个正整数,且不超过之前执行指令数 In

CSU 1416 Practical Number

原题链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1416 结论题,具体判断方法请点击这个网址. 筛素数是肯定的,但一开始定的范围太大了,想当然要筛到10^9的质数,但仔细想想,只要到sqrt(10^9)就可以了,最后的那一个质数是最后一步的比较,不用筛出来. #include <stdio.h> #include <string.h> #include <iostream> using namespace st

CSU 1412 Line and Circles

原题链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1412 题目要求判断是否有一条直线可以穿过所有的圆. 做法:把所有圆心做一次凸包,然后判断这个凸包是否能通过一个宽度为2*R的通道. 做法和求凸包直径差不多,只是判断的时候把点到两个端点的距离换成点到直线的距离. #include <stdio.h> #include <string.h> #include <math.h> #include <stdli

CSU 1547 Rectangle(dp、01背包)

题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1547 Description Now ,there are some rectangles. The area of these rectangles is 1* x or 2 * x ,and now you need find a big enough rectangle( 2 * m) so that you can put all rectangles into it(th

CSU 1601 War (并查集)

1601: War Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 202  Solved: 58 [Submit][Status][Web Board] Description AME decided to destroy CH's country. In CH' country, There are N villages, which are numbered from 1 to N. We say two village A and B ar

CSU - 1542 Flipping Parentheses (线段树)

CSU - 1542 Flipping Parentheses Time Limit: 5000MS   Memory Limit: 262144KB   64bit IO Format: %lld & %llu Submit Status Description Input Output Sample Input 6 3 ((())) 4 3 1 Sample Output 2 2 1 Hint 题意:先给出一个符合括号匹配的字符串,然后Q次操作 每次操作将某个括号反转,问将哪个括号反转能使字