[题解]bzoj2328(HNOI2011)赛车游戏

这里写图片描述

Solution

首先我们要知道一点,在保证各个路段速度基本相同的情况下最优(并不知道怎么证明,望大神指导)。所以我们二分速度,检验是否超出油量限制。然后根据二分出的速度计算答案。注意有一点:如果在某段下坡路上,对于当前速度 v av+bs<0 ,那么意味着你可以再加一点速使答案更优同时此段耗油依旧为0。所以计算的时候要特判一下。

这题精度卡得很严,计算的时候我开的是1e-14,二分的时候要用限制二分次数的方法防止tle。

代码:

#include
#include
#include
#include
using namespace std;

const int maxn=10010;
const double eps=1e-14;
struct road{
    double x,y,s,len;
    void init(){
        s=y/x;
        x/=1000.0;y/=1000.0;
        len=sqrt(x*x+y*y);
    }
}e[maxn];
int T,r;
double a,b,vmax,f;

bool check(double v){
    double re=0;
    for(int i=1;i<=r;i++){
        re+=max(a*v+b*e[i].s,(double)0)*e[i].len;
        if(re+eps>=f)break;
    }
    return re+epsdouble calc(double v){
    double re=0;
    for(int i=1;i<=r;i++){
        double temp=a*v+b*e[i].s;
        if(temp<=eps){
            double vv=(-b*e[i].s)/a;
            vv=min(vv,vmax);//计算下坡上最大的合法速度
            re+=e[i].len/vv;
        }
        else{
            if(v<=eps)return 0;
            re+=e[i].len/v;
        }
    }
    return re;
}
double binary(double l,double r){
    double mid;
    int t=1;
    while(t<=1000){
        mid=(l+r)/2.0;
        if(check(mid))l=mid;
        else r=mid;
        t++;
    }
    return calc(l);
}

int main(){
    scanf("%d",&T);
    while(T--){
        memset(e,0,sizeof e);
        scanf("%lf%lf%lf%lf%d",&a,&b,&vmax,&f,&r);
        for(int i=1;i<=r;i++){
            scanf("%lf%lf",&e[i].x,&e[i].y);
            e[i].init();
        }
        double ans=binary(0,vmax);
        if(ans<=eps)puts("IMPOSSIBLE");
        else printf("%.5lf\n",ans);
    }
}

你可能感兴趣的:(二分答案,题解,HNOI2011,二分答案)