Codeforces 590B Chip 'n Dale Rescue Rangers

题意:
一艘飞船相对空气的最大速度是V,一开始风速是 F⃗ 1 (x1,y1), T秒后风速变为 F⃗ 2 (x2, y2),求从s点(a1,b1)到e点(a2,b2)的最短时间.输入保证飞船相对空气的最大速度大于风速.
分析:
这道题很巧妙的利用了向量的性质,当最短时间 tT 的时候很明显可以直接计算出答案,现在考虑 t>T 的时候, 设飞船前T秒的速度为 v⃗ 1 , 后t-T秒的速度为 v⃗ 2 , 这样可以得到等式 (F⃗ 1+v⃗ 1)T+(F⃗ 2+v⃗ 2)(tT)=se . 然后进行变形可以得到 F⃗ 1T+F⃗ 2(tT)+v⃗ 1T+v⃗ 2(tT)=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;
}

你可能感兴趣的:(codeforces,物理,二分,计算几何)