2019杭电多校第一场题解

17 篇文章 0 订阅
11 篇文章 0 订阅

1004

题意: 给你n+1辆车的车头距离终点的位置和车身长度, 以及每辆车的初始速度, 车子不会加速,当遇到前面一辆车的时候车子会瞬间减速并且和前面一辆速度相等,并且通过了终点线的车辆并不会停下来会继续行驶,问第0辆车的车头到达终点线所需要的总时间。

理解:当第0辆车经过终点线的时候无疑只有两种状态,1.以原来的速度行驶,2.与前面一辆车靠在一起并且以前面一辆车的速度行驶

做法1:

注意到第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<iostream>
#include<stack>
#include<cmath>
#include<cstdio>
#include<math.h>
#include<queue>
#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;
}

做法2:

考虑第0辆车到达终点时的情况

1.以v[0]行驶

2.和前1辆车靠在一起以v[1]速度行驶

3.和前2辆车靠在一起以v[2]速度行驶

......

于是我们可以从前往后枚举 这n+1种情况,将所求的时间取max 

#include<iostream>
#include<stack>
#include<cmath>
#include<cstdio>
#include<math.h>
#include<queue>
#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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值