Description
给定一条长度为
l的道路,现在你从原点出发向
l这个点行驶,你的加速度为
a,
d这个点的限速为
w,你车辆的最高速度为
v,求行驶到
l点的最短时间
数据范围:不爆
double
Solution
一道物理题
匀速运动时:
v=ts
匀变速时:
v=v0+at
位移公式:
x=v0t+2at2
位移速度关系式:
v2−v02=2ax
第四条证明:
由第三条
x=v0t+2at2
两边同时乘
2a得到
2v0at+a2t2=2ax
分配率
at(2v0+at)=2ax
由第二条
at(v+v0)=2ax
再由第二条移项得到
(v−v0)(v+v0)=2ax
平方差
v2−v02=2ax
简单吧。。。
设函数
f(v0,v,a,l)表示初始速度为
v1,限速
v2,加速度
a,通过长度为
l的路程的时间
设位移距离
s=2av2−v02
如果
s≥l,那么直接跑即可,得到方程
21at2+v0t−l=0,用公式法解得
t=a−v0+v02+2al
否则前面做加速,后面做匀速
得到
t=av−v0+vl−s,即加速的时间和通过剩余路程的时间
主程序部分
设
s特判=2aw2,表示加速到
w行驶的距离
当
w≥v or s特判≥d时,即连最高时速都没有限速那么高或者一直加速
w时已经过了
d了,这时限不限速就不重要了,直接一直加速到
v开过去即可,
ans=f(0,v,a,l)
当
w<v时,设
t1表示
[0∼d]的时间,
t2表示
[d∼l]的时间,显然
t2=f(w,v,a,l−d)
现在我们的主要任务是求
t1,我们可以模仿人的开车过程
当没有摄像头时,你一直加速到最高时速,发现前方有摄像头,你又慢慢减速到限速,我们此时就需要求出这个你开始减速的时间
又是一个一元二次方程啊。。。
t加速阶段=2a22ad+w2
若
at加速阶段≤v,那么我们来不及加速到
w,只能加速到某一速度,然后减速到
v,此时
t加速=t减速到0
得到
t1=t加速阶段+t减速到w=t加速阶段+(t减速到0−t加速到w)=2t加速阶段−t加速到w=2t加速阶段−aw
否则若
at加速阶段>v,则说明我们时间足够充裕,可以先加速到
w,然后匀速行驶一段时间,再减速到
v,此时
t1=av+av−w+vd−(加速路程+减速路程),分别表示加速的时间,减速的时间和匀速行驶的时间
答案即为
t1+t2
说白了就是一道物理题呀QwQ
时间复杂度?
O(1)
Code
#include<cstdio>
#include<cmath>
using namespace std;
double a,v,l,d,w,t1,t2,ans;
inline double F(double x){return x*x;}
inline double f(double v0,double v,double a,double l)
{
double s=(v+v0)*(v-v0)/2/a;
if(s>=l) return (-v0+sqrt(F(v0)+2*a*l))/a;
else return (v-v0)/a+(l-s)/v;
}
signed main()
{
scanf("%lf%lf%lf%lf%lf",&a,&v,&l,&d,&w);
double stp=F(w)/2/a;
if(w>=v||stp>=d) ans=f(0,v,a,l);
else
{
t2=f(w,v,a,l-d);
double tjs=sqrt((2*a*d+F(w))/2/a/a);
if(tjs*a<=v) t1=2*tjs-w/a;
else
{
double sf=F(v)/2/a;
double sl=(v+w)*(v-w)/2/a;
t1=v/a+(v-w)/a+(d-sf-sl)/v;
}
ans=t1+t2;
}
printf("%.12f",ans);
}