2020icpc上海 Walker (三分)

题目链接:D-Walker_第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(上海) (nowcoder.com)s​​​​​​​a

题意,给你一个线段,端点是0,n,现在给你两个点的位置以及他们的移动速度,问最小需要花费多长时间能够走完整个线段。

这个题目需要分情况讨论:

我们下面只讨论p1在p2左边的情况, p1在p2右边的情况可类似得到

第一种情况是质点1走完全程

第二种情况是质点2走完全程

第三种情况是质点1从p1跑到l,质点2从p2跑到0

第四种情况是质点p1跑完0~Q这段线段,质点p2跑完Q~L这段线段

前三种情况都比较容易求,我在这就不赘述了,最关键的是第四种情况的求法

对于第四种情况我们可以用三分求,枚举Q点,分别计算质点p1跑完0~Q这段线段的最小时间和质点p2跑完Q~L这段线段的最小时间,最后取一个最大值就好了,我们看看如何求p1跑完0~Q这段线段的最小时间,p1有两条路线可走,一个是从p1->Q->0,另一个是从p1->0->Q,分别求出这两种方式的时间取一个最小值即可,质点p2跑完Q~L这段线段的最小时间同理可求得。最后我们直接三分枚举最优点Q即可。

下面是代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cmath>
using namespace std;
double l,p1,v1,p2,v2;
//计算以速度v从a点到x点再到b点所要花费的时间 
double f(double a,double x,double b,double v)
{
	double t=(fabs(x-a)+fabs(x-b))/v;
	return t;
}
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		scanf("%lf%lf%lf%lf%lf",&l,&p1,&v1,&p2,&v2);
		double x=(min(p1,l-p1)+l);//计算第一个点跑完整个路线花费的时间 
		double t=x/v1;
		x=(min(p2,l-p2)+l);//计算第二个点跑完整个路线花费的时间 
		t=min(t,x/v2);
		if(p1<=p2)
		{
			t=min(t,max((l-p1)/v1,p2/v2));//计算两点向相反方向跑完整个路线花费的时间 
			double ll=p1,rr=p2,lmid,rmid;
			while(rr-ll>0.0000000001)//三分求取最优点 
			{
				lmid=ll+(rr-ll)/3;
				rmid=rr-(rr-ll)/3;
				if(max(min(f(p1,0,lmid,v1),f(p1,lmid,0,v1)),min(f(p2,l,lmid,v2),f(p2,lmid,l,v2)))>max(min(f(p1,0,rmid,v1),f(p1,rmid,0,v1)),min(f(p2,l,rmid,v2),f(p2,rmid,l,v2)))) ll=lmid;
				else rr=rmid;
			}
			t=min(t,max(min(f(p1,0,ll,v1),f(p1,ll,0,v1)),min(f(p2,l,ll,v2),f(p2,ll,l,v2))));
		}
		else
		{
			t=min(t,max((l-p2)/v2,p1/v1));//计算两点向相反方向跑完整个路线花费的时间 
			double ll=p2,rr=p1,lmid,rmid;
			while(rr-ll>0.0000000001)//三分求取最优点 
			{
				lmid=ll+(rr-ll)/3;
				rmid=rr-(rr-ll)/3;
				if(max(min(f(p1,l,lmid,v1),f(p1,lmid,l,v1)),min(f(p2,0,lmid,v2),f(p2,lmid,0,v2)))>max(min(f(p1,l,rmid,v1),f(p1,rmid,l,v1)),min(f(p2,0,rmid,v2),f(p2,rmid,0,v2)))) ll=lmid;
				else rr=rmid;
			}
			t=min(t,max(min(f(p1,l,ll,v1),f(p1,ll,l,v1)),min(f(p2,0,ll,v2),f(p2,ll,0,v2))));
		}
		printf("%.10f\n",t);
	}
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值