题意:
一艘飞船相对空气的最大速度是V,一开始风速是
F⃗ 1
(x1,y1), T秒后风速变为
F⃗ 2
(x2, y2),求从s点(a1,b1)到e点(a2,b2)的最短时间.输入保证飞船相对空气的最大速度大于风速.
分析:
这道题很巧妙的利用了向量的性质,当最短时间
t≤T
的时候很明显可以直接计算出答案,现在考虑
t>T
的时候, 设飞船前T秒的速度为
v⃗ 1
, 后t-T秒的速度为
v⃗ 2
, 这样可以得到等式
(F⃗ 1+v⃗ 1)∗T+(F⃗ 2+v⃗ 2)∗(t−T)=se→
. 然后进行变形可以得到
F⃗ 1∗T+F⃗ 2∗(t−T)+v⃗ 1∗T+v⃗ 2∗(t−T)=se→
, 这样因为
F⃗ 1,F⃗ 2
已知,可以看出t给出后,前半部分可以直接计算出来,后半部分
v1,v2
肯定取最大速度最快,这样就可以直接二分t,然后判断这个等式是否能够成立,就可以计算出来最小速度.不看数学表达式,这道题有个很物理的想法,风和飞船速度的合速度可以拆开,让风先吹ts,看飞船落在哪个地方,然后让飞船满速向目标地点前进,判断在给定时间t内,飞船能否飞到目标地点.因为如果ts内不能达到,肯定<=ts内也不能达到.所以就可以二分解决这个问题.
代码:
#include <bits/stdc++.h>
using namespace std;
const double inf = 1e15;
struct P
{
double x, y;
P(double x = 0, double y = 0):x(x), y(y) {}
P operator + (P b) {
return P(x + b.x, y + b.y);
}
P operator * (double k) {
return P(k*x, k*y);
}
};
double dist(P a, P b) {
return sqrt((b.x - a.x)*(b.x - a.x) + (b.y - a.y)*(b.y - a.y));
}
P s, e;
P v1, v2;
double maxv, T;
bool check(double t)
{
double lt = t - T;
P cur = s;
cur = cur + (v1*min(t, T));
if(lt > 0) {
cur = cur + (v2 * lt);
}
double d = dist(cur, e);
return maxv*t > d;
}
int main()
{
cin >> s.x >> s.y >> e.x >> e.y;
cin >> maxv >> T;
cin >> v1.x >> v1.y >> v2.x >> v2.y;
double l = 0, r = 1e15;
for(int i = 0; i < 200; i++) {
double m = (l + r) / 2;
if(check(m)) {
r = m;
} else {
l = m;
}
}
printf("%.9f\n", l);
return 0;
}