zoukankan      html  css  js  c++  java
  • bzoj2876 [Noi2012]骑行川藏

    Description

    蛋蛋非常热衷于挑战自我,今年暑假他准备沿川藏线骑着自行车从成都前往拉萨。川藏线的沿途有着非常美丽的风景,但在这一路上也有着很多的艰难险阻,路况变化多端,而蛋蛋的体力十分有限,因此在每天的骑行前设定好目的地、同时合理分配好自己的体力是一件非常重要的事情。
    由于蛋蛋装备了一辆非常好的自行车,因此在骑行过程中可以认为他仅在克服风阻做功(不受自行车本身摩擦力以及自行车与地面的摩擦力影响)。某一天他打算骑 N段路,每一段内的路况可视为相同:对于第i段路,我们给出有关这段路况的3个参数 si , ki , vi' ,其中 si 表示这段路的长度, ki 表示这段路的风阻系数, vi' 表示这段路上的风速(表示在这段路上他遇到了顺风,反之则意味着他将受逆风影响)。若某一时刻在这段路上骑车速度为v,则他受到的风阻大小为 F = ki ( v - vi' )2(这样若在长度为s的路程内保持骑行速度v不变,则他消耗能量(做功)E = ki ( v - vi' )2 s)。
    设蛋蛋在这天开始时的体能值是 Eu ,请帮助他设计一种行车方案,使他在有限的体力内用最短的时间到达目的地。请告诉他最短的时间T是多少。

    【评分方法】
    本题没有部分分,你程序的输出只有和标准答案的差距不超过0.000001时,才能获得该测试点的满分,否则不得分。

    【数据规模与约定】
    对于10%的数据,N=1;
    对于40%的数据,N<=2;
    对于60%的数据,N<=100;
    对于80%的数据,N<=1000;
    对于所有数据,N <= 10000,0 <= Eu <= 108,0 < si <= 100000,0 < ki <= 1,-100 < vi' < 100。数据保证最终的答案不会超过105。

    【提示】
    必然存在一种最优的体力方案满足:蛋蛋在每段路上都采用匀速骑行的方式。

    Input

    第一行包含一个正整数N和一个实数Eu,分别表示路段的数量以及蛋蛋的体能值。 接下来N行分别描述N个路段,每行有3个实数 si , ki , vi' ,分别表示第 i 段路的长度,风阻系数以及风速。

    Output

    输出一个实数T,表示蛋蛋到达目的地消耗的最短时间,要求至少保留到小数点后6位。

    Sample Input


    3 10000
    10000 10 5
    20000 15 8
    50000 5 6

    Sample Output

    12531.34496464
    【样例说明】 一种可能的方案是:蛋蛋在三段路上都采用匀速骑行的方式,其速度依次为5.12939919, 8.03515481, 6.17837967。

    正解:拉格朗日乘子法+二分答案。

    ZYT学长的题解:http://www.cnblogs.com/MashiroSky/p/6368825.html

    其实这道题暴力还是挺简单的,直接三分就行了。。

    然而这道题我不知道怎么求偏导数,我连偏导数是什么都不知道,虽然我知道只有偏导数才是难点。。

    拉格朗日乘子法可以解决如下问题:

    在满足$g(x1,x2,...)=c$(c为常数)的情况下,求出$f(x1,x2,...)$的最小值。

    然后接下来的话不是人话:

    我们可以发现,$f$取最值时,$f$和$g$的等高线相切。当等高线相切时$f$和$g$的梯度向量平行,也就是$ abla f// abla g$。

    然后梯度向量的每一维就对应$f$每一维的偏导数。具体表示见ZYT学长博客。。

    我们求出偏导数以后,可以列出$n$个方程,再加上一个约束,也就是$n+1$个方程。

    如果忽略上面的步骤那么这道题还是很容易的。。

    于是最后的方程就是这样:$2lambda k_{i}v_{i}^{2}(v_{i}-{v_{i}}')=-1$

    再加上一个约束条件就是:$sum_{i=1}^{n}k_{i}(v_{i}-v_{i}^{'})s_{i}=E$

    我们可以很容易发现,$v_{i}$的下限是$v_{i}^{'}$,上限是每段路用$E$能量的速度(然而因为$s_{i}$可能为$0$所以要用$inf$)。

    所以,$k_{i}v_{i}^{2}(v_{i}-{v_{i}}')>0$,那么$lambda <0$。且随$lambda $增大,$v_{i}$也增大;随着$v_{i}$增大,$E$增大,方程减小。

    那么思路就很明显了,首先二分$lambda$,然后再二分得出$v_{i}$,每次二分$lambda$时判断能量总和是否超过$E$,每次二分$v_{i}$时判断方程是否满足大于等于$1$。这样,我们就能求出每个$v_{i}$,算出答案了。

     1 //It is made by wfj_2048~
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <complex>
     5 #include <cstring>
     6 #include <cstdlib>
     7 #include <cstdio>
     8 #include <vector>
     9 #include <cmath>
    10 #include <queue>
    11 #include <stack>
    12 #include <map>
    13 #include <set>
    14 #define eps (1e-13)
    15 #define inf (1e18)
    16 #define N (10010)
    17 #define il inline
    18 #define RG register
    19 #define ll long long
    20 #define ld long double
    21 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    22 
    23 using namespace std;
    24 
    25 ld s[N],k[N],v[N],vv[N],E,ans,lambda;
    26 int n;
    27 
    28 il int check(RG ld key){
    29     RG ld res=0,l,r,mid;
    30     for (RG int i=1;i<=n;++i){
    31     l=max((ld)0.0,vv[i]),r=inf,v[i]=l;
    32     while (l<=r){
    33         mid=(l+r)/2;
    34         if (2*key*k[i]*mid*mid*(mid-vv[i])>=-1) v[i]=mid,l=mid+eps; else r=mid-eps;
    35     }
    36     res+=k[i]*s[i]*(v[i]-vv[i])*(v[i]-vv[i]);
    37     }
    38     return res<=E;
    39 }
    40 
    41 il void work(){
    42     scanf("%d%Lf",&n,&E);
    43     for (RG int i=1;i<=n;++i) scanf("%Lf%Lf%Lf",&s[i],&k[i],&vv[i]);
    44     RG ld l=-inf,r=0.0,mid;
    45     while (l<=r){
    46     mid=(l+r)/2;
    47     if (check(mid)) lambda=mid,l=mid+eps; else r=mid-eps;
    48     }
    49     check(lambda);
    50     for (RG int i=1;i<=n;++i) ans+=s[i]/v[i];
    51     printf("%0.9Lf",ans); return;
    52 }
    53 
    54 int main(){
    55     File("bicycle");
    56     work();
    57     return 0;
    58 }
  • 相关阅读:
    hdu6229 Wandering Robots 2017沈阳区域赛M题 思维加map
    hdu6223 Infinite Fraction Path 2017沈阳区域赛G题 bfs加剪枝(好题)
    hdu6438 Buy and Resell 买卖物品 ccpc网络赛 贪心
    hdu6441 Find Integer 求勾股数 费马大定理
    bzoj 1176 Mokia
    luogu 3415 祭坛
    bzoj 1010 玩具装箱
    bzoj 3312 No Change
    luogu 3383【模板】线性筛素数
    bzoj 1067 降雨量
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6549862.html
Copyright © 2011-2022 走看看