题意: 给你n+1辆车的车头距离终点的位置和车身长度, 以及每辆车的初始速度, 车子不会加速,当遇到前面一辆车的时候车子会瞬间减速并且和前面一辆速度相等,并且通过了终点线的车辆并不会停下来会继续行驶,问第0辆车的车头到达终点线所需要的总时间。
理解:当第0辆车经过终点线的时候无疑只有两种状态,1.以原来的速度行驶,2.与前面一辆车靠在一起并且以前面一辆车的速度行驶
注意到第0辆车经过终点线的时间最多为 1e9 ,最少为1,我们可以在这个区间里对答案二分。
思维点:如何判定答案是否可行?
容易发现,第n辆车的行驶是不受第n-1辆车的控制的而只会受到第n+1辆车的控制。所以我们可以从后往前考虑每一辆车
判断剩余的车是否能够过线并且维护下一辆车的车头在时间为t时最多能够到达的位置。
预处理出车辆长度的前缀和sum[i]。
当前车的车头的位置 pos[i]=max(s[i]-v[i]*t, mx)
判断 pos[i]>sum[i](第1到第i车的车辆总长度)
更新 mx=pos[i]+l[i];
#include
#include
#include
#include
#include
#include
#define ll long long
using namespace std;
const int maxn=1e5+10;
const double Exp=1e-7;
ll l[maxn],s[maxn],v[maxn],sum[maxn];
int n;
double t,tl,tr;
double pos[maxn];
bool check(double time)
{
double mx=-1e9;
for(int i=n;i>=0;i--)
{
pos[i]=max(s[i]*1.0-v[i]*t,mx);
if (pos[i]>-sum[i]) return false;
mx=pos[i]+l[i]; //头最大能到达的位置
}
return true;
}
int main(){
while(~scanf("%d",&n))
{
for(int i=0;i<=n;i++)scanf("%lld",&l[i]);
for(int i=0;i<=n;i++)scanf("%lld",&s[i]);
for(int i=0;i<=n;i++)scanf("%lld",&v[i]);
sum[0]=0;
for (int i=1;i<=n;i++) sum[i]=sum[i-1]+l[i];
tl=0,tr=1e9;
while(abs(tl-tr)>Exp)
{
t=(tl+tr)/2.0;
if(check(t))
{
tr=t;
}
else
{
tl=t;
}
}
printf("%.10f\n",t);
}
return 0;
}
考虑第0辆车到达终点时的情况
1.以v[0]行驶
2.和前1辆车靠在一起以v[1]速度行驶
3.和前2辆车靠在一起以v[2]速度行驶
......
于是我们可以从前往后枚举 这n+1种情况,将所求的时间取max
#include
#include
#include
#include
#include
#include
#define ll long long
using namespace std;
const int maxn=1e5+10;
const double Exp=1e-7;
ll l[maxn],s[maxn],v[maxn],sum[maxn];
int n;
int main()
{
while(~scanf("%d",&n))
{
for(int i=0;i<=n;i++)scanf("%lld",&l[i]);
for(int i=0;i<=n;i++)scanf("%lld",&s[i]);
for(int i=0;i<=n;i++)scanf("%lld",&v[i]);
ll sum=0;
double ans=s[0]*1.0/v[0];
for(int i=1;i<=n;i++)
{
ans=max(ans,((sum+=l[i])+s[i])*1.0/v[i]);
}
printf("%.10f\n",ans);
}
return 0;
}