ICPC2020上海区域赛D题

链接:https://ac.nowcoder.com/acm/contest/9925/D
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 1048576K,其他语言2097152K
Special Judge, 64bit IO Format: %lld
题目描述
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]}. There are two travelers on it. The first one is on position p1​ with velocity v1 (which means s/he can walk v1 unit on the segment per second). The second one is on position p2 with velocity v2.

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) – the number of test cases.

The i-th of the next test lines contains five numbers n,p1,v1,p2,v2, 0<n,p1,i , p2,i≤10000, 0.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 −6 .
示例1
输入

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

思路:3种方式走完整个区间:1.一个人走完全部路,2.2个人相互走到对面 3.两个人完成离自己近的端点后,往中间走
代码:

#include<bits/stdc++.h>
using namespace std;

//计算位置在p点这个人覆盖区间长度为n需要的最短时间
double fun(double p, double n, double v)
{               //先往左走  先往右走
    return min((p + n) / v, (n-p + n) / v);
}

void  solve()
{
    double n, p1, p2, v1, v2;
    scanf("%lf%lf%lf%lf%lf", &n, &p1, &v1, &p2, &v2);
    double ans = 9999999999;

    if(p1 >= p2){
        swap(p1, p2);
        swap(v1, v2);
    }

    //一个人走完
    ans = min(ans, fun(p1, n, v1));
    ans = min(ans, fun(p2, n, v2));

    //左边那个人走右边去,右边那个人走左边去
    ans = min(ans, max( (n - p1) / v1, p2 / v2));

    double l = p1;
    double r = p2;
    for(int i = 1; i <= 100; i++){
        double mid = (l + r ) / 2; //相遇的位置
        double ans1 = fun(p1, mid, v1);//左边那个人需要 的时间
        double ans2 = fun(n - p2, n - mid, v2);//右边那个人需要的时间
        ans = min(ans, max(ans1, ans2));

        if(ans1 < ans2){//左边的时间短,右边时间长,p往右移动
            l = mid;
        }
        else
            r = mid;
    }
    printf("%.10f\n", ans);
}

int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
        solve();
    return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值