第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(上海)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]. There are two travelers on it. The first one is on position p 1 p_1 p1withvelocity v 1 v_1 v1(which means s/he can walk v 1 v_1 v1unit on the segment per second). The second one is on position p 2 p_2 p2with velocity v 2 v_2 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.

在这里插入图片描述

题意

给定数轴的长度,两个人的初始位置和速度
两个人在数轴上走路,问两个人路程覆盖整个数轴的最短时间是多少

思路

分三种情况
1.两个人分别把全程走完
2.两个人相对走,求两个人走到另一头的最大时间即可
3.在p1和p2之间选一个分界点,让两人各自走完靠自己最近那边后到达分界点,二分分界点,让两人走过分界点的时间尽可能的接近,100次二分可以保证精度足够1e-6
具体见代码注释

代码

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

//在pos位置覆盖到区间n需要的最短时间 
double get_dis(double pos,double v,double n)
{	
	double a = (pos + n) / v; // 往左走到l再走到n 
	double b = (n - pos + n) / v; //往右走到r再走到n 
	return min(a,b); // 取最小值 
}

void Solve()
{
	double n,p1,v1,p2,v2;
	scanf("%lf%lf%lf%lf%lf",&n,&p1,&v1,&p2,&v2);
	
	if(p1 > p2)
	{
		swap(p1,p2);
		swap(v1,v2);
	}
	double ans = 9999999999999999;
	
	// 1.自己走完全程用的时间 
	ans = min(ans , get_dis(p1,v1,n));
	ans = min(ans , get_dis(p2,v2,n));
	
	// 2.相对走完自己的路程 
	ans = min(ans , max((n-p1)/v1 , p2/v2));
	
//	cout<<ans<<endl;
	double l = p1,r = p2; // 在p1和p2之间寻找一个分界点 
	for(int i=1;i<=100;i++) //  二分分界点 
	{
		double mid = (l + r) / 2; //分界点 
		double ans1 = get_dis(p1,v1,mid); 
		double ans2 = get_dis(n-p2,v2,n-mid);
		ans = min(ans,max(ans1,ans2));
		if(ans1 < ans2) l = mid; // 让到达分界点的时间尽可能的相同 
		else r = mid;
	}
	printf("%.12f",ans);
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		Solve();
		if(t) puts("");
	} 
}

/*
2
10000.0 1.0 0.001 9999.0 0.001
4306.063 4079.874 0.607 1033.423 0.847
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值