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

这里写图片描述

Solution

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

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

代码:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
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+eps<f;
}
double 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);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值