20年上海站D题Walker(二分,简洁)

题目描述

As a world-famous traveler, Prof. Pang's research interest is to travel as many places as possible in his life.

We have a segment [0,n]{[0, n]}[0,n]. There are two travelers on it. The first one is on position p1p_1p1​ with velocity v1v_1v1​ (which means s/he can walk v1v_1v1​ unit on the segment per second). The second one is on position p2p_2p2​ with velocity v2v_2v2​.

From their respective beginning points, travelers can walk on the segment. They cannot walk outside the segment. Whenever they want to change their direction, they can turn around immediately.

Please help Prof. Pang to calculate the minimum possible time by which every position of the segment is passed by at least one traveler.

输入描述:

The first line contains one integer test (1≤test≤10000)test~(1\le test\le 10000)test (1≤test≤10000) -- the number of test cases.

The i-th of the next test lines contains five numbers n,p1,i,v1,i,p2,i,v2,in, p_{1, i}, v_{1, i}, p_{2, i}, v_{2, i}n,p1,i​,v1,i​,p2,i​,v2,i​ (0<n≤100000 < n \le 100000<n≤10000, 0≤p1,i,p2,i≤n0\le p_{1, i},p_{2, i} \le n0≤p1,i​,p2,i​≤n, 0.001≤v1,i,v2,i≤10000.001 \le v_{1, i},v_{2, i} \le 10000.001≤v1,i​,v2,i​≤1000). All numbers have at most 3 digits after the decimal point.

输出描述:

For each test case, we should output one number -- the minimum time that every position of the segment is passed by at least one traveler.

Your answer is considered correct if its absolute or relative error does not exceed 10−610^{-6}10−6.

输入

2
10000.0 1.0 0.001 9999.0 0.001
4306.063 4079.874 0.607 1033.423 0.847

输出

5001000.0000000000
3827.8370013755

题意:0-n的一维坐标上,给任意两点的位置和速度,他们可以任何时候去任何方向,求这两个点共同走完所有地方需要最少的时间。

思路:

首先判断是否是前一个位置更小,不是的话swap翻转一下,前面的为a,后面为b

做题思路不是特别难,分三中情况:

1.只用a或者b,答案就是:(x+min(a.x,x-a.x))/a.v,和(x+min(b.x,x-b.x))/b.v),因为a或者b可以选择先到达左端点还是右端点

2.a和b交叉走,且交叉一直走。答案就是:max(b.x/b.v,(x-a.x)/a.v),最大使用时间即是答案。

隔壁拿的图,侵删

3.左边由a来走,右边由b来走。中间的点为mid,则mid一定在a和b起始点之间,因为一旦a向右超过了b起始点,那么b就不用往右走了,b就没用了,属于第一种情况了。

侵删

 这种就是mid左边是a来走,右边是b来走

a走的最短路径就是:mid+min(a.x,mid-a.x)

b走的最短路径就是:l-mid+min(n-b.x,b.x-mid)

而且是小数的答案,两边的最大值是答案,一定是左右使用时间相同时最优,这个过程可以二分。

这题还有一点很重要,就是精度问题,以至于有的题解有100次二分的for

但如我下面的代码,没有long double,没有1e-10,没有多小数位输出

这题的精度卡的是那个二分返回的结果:return max(l/a.v+(min(a.x,l-a.x))/a.v,((x-l)+min(x-b.x,b.x-l))/b.v);

一定是max()的,不能只返回一个,这个要看代码规范了。

代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define dou double
#define EXP 0.0000001
#define M 1000005
int T;
dou x;
struct Node{
    dou x,v;
}a,b;
bool check(dou mid){
    return (mid+min(a.x,mid-a.x))/a.v>((x-mid)+min(x-b.x,b.x-mid))/b.v;
}
dou solve(){
    dou l=a.x,r=b.x;
    while(r-l>EXP){
        dou mid=(l+r)/2;
        if(check(mid)) r=mid;
        else l=mid;
    }
    return max(l/a.v+(min(a.x,l-a.x))/a.v,((x-l)+min(x-b.x,b.x-l))/b.v);        //这里一定是max,只返回左边时间或右边时间会WA
}
int main(){
    cin>>T;
    while(T--){
        cin>>x>>a.x>>a.v>>b.x>>b.v;
        if(a.x>b.x) swap(a,b);
        dou ans=(x+min(a.x,x-a.x))/a.v;
        ans=min(ans,(x+min(b.x,x-b.x))/b.v);
        ans=min(ans,max(b.x/b.v,(x-a.x)/a.v));
        printf("%.6lf\n",min(ans,solve()));
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

int 我

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值