跑步(简易版) 题解
#5285. YAOI Round #26 (Div.1+Div.2) C. 跑步(简易版)
解法 1
跑道上在两个人之间选一个位置,使得自己有最长的时间不与他们相遇。
根据题目条件,很容易发现自己与 A 相距 \(y\),与 B 相距 \(x-y\)。

因此自己与 A 相遇的时间即为 \(\dfrac{y}{v_1-v_0}\),与 B 相遇的时间为 \(\dfrac{x-y}{v_0-v_2}\)。题目求与两人中任意一人相遇的时间最长,可以转换为使这两个等式相等(即同时相遇,时间为最长的)(基础的小学数学)。因此简单地推推柿子:
\[\begin{aligned}\\
\dfrac{y}{v_1-v_0} &= \dfrac{x-y}{v_0-v_2}\\
y \times (v_0-v_2) &= (x-y) \times (v_1-v_0)\\
y \times (v_0-v_2+v_1-v_0) &= x \times (v_1-v_0)\\
y \times (v_1-v_2) &= x \times (v_1-v_0)\\
y &= \dfrac{x \times (v_1-v_0)}{(v_1-v_2)}\\
\end{aligned}\]
得到 \(y = \dfrac{x \times (v_1-v_0)}{(v_1-v_2)}\),而等式右边所有的量都是已知的,因此可以直接代入计算。
解法 2
如果上面推柿子看不懂的可以来看看这种解法。
首先我们拿样例出来手推一下答案:
| y | 4 | 8 | 12 | 16 | 20 | 24 | 28 |
|---|---|---|---|---|---|---|---|
| ans(追及时间) | 1 | 2 | 3 | 4 | 5 | 3 | 1 |
把得到的结果画一个图出来,可以发现是一个单峰函数(中间凸起,最高点左侧单调上升,右侧单调下降)。因此我们可以直接三分或者使用爬山算法(两种很常用的算法,尤其是后者和模拟退火,建议自行学习)。
代码
公式
#include<bits/stdc++.h>
using namespace std;
int main(){
double x,v0,v1,v2;
scanf("%lf%lf%lf%lf",&x,&v0,&v1,&v2);
printf("%.4lf",x*(v1-v0)/(v1-v2));
return 0;
}
三分
#include<bits/stdc++.h>
using namespace std;
int x,v0,v1,v2;
double l,r,mid,eps=1e-6;
double getans(double y){
return min(y/(v1-v0),(x-y)/(v0-v2));
}
int main(){
scanf("%d%d%d%d",&x,&v0,&v1,&v2);
l=0,r=x;
while(r-l>=eps){
mid=(l+r)/2;
if(getans(mid-eps)<getans(mid+eps))l=mid;
else r=mid;
}
printf("%.4lf",mid);
return 0;
}

浙公网安备 33010602011771号