第 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)withvelocity (v_1)(which means s/he can walk (v_1)unit on the segment per second). The second one is on position(p_2)with velocity(v_2)

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
*/
原文地址:https://www.cnblogs.com/liangyj/p/14195187.html