Solution
首先我们要知道一点,在保证各个路段速度基本相同的情况下最优(并不知道怎么证明,望大神指导)。所以我们二分速度,检验是否超出油量限制。然后根据二分出的速度计算答案。注意有一点:如果在某段下坡路上,对于当前速度
v
,
这题精度卡得很严,计算的时候我开的是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);
}
}