CF 8D Two Friends 【二分+三分】

三个地点构成一个三角形。

判断一下两个人能否一起到shop然后回家,如果不能:

两个人一定在三角形内部某一点分开,假设沿着直线走,可以将问题简化。

三分从电影院出来时候的角度,在对应的直线上二分出一个分离点即可。

三分角度的方法:在shop和home两个点之间找一个点p,链接p和电影院,在这个线段上面二分出分离点。



注意:精度。


#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
#define sqr(x) ((x)*(x))
#define eps 1e-6

struct POINT {
    double x, y;
    POINT() {}
    POINT(double _x, double _y): x(_x), y(_y) {}
} c, s, h;
double t1, t2;

double dist(POINT &x, POINT &y) {
    return sqrt(sqr(x.x-y.x) + sqr(x.y-y.y));
}
double calc(double m) {
    POINT a = POINT(s.x*(1-m) + h.x*m, s.y*(1-m) + h.y*m);
    POINT b;
    double ac = dist(a, c);
    double ah = dist(a, h);
    double as = dist(s, a);
    if (ac + ah <= t2 && ac + as <= t1) {
        return min(t2-ah, t1-as);
    }
    double l = 0, r = 1, mid, la, lb, lc;
    for (int i=0; i<300; i++) {
        mid = (l + r)/2.0;
        b = POINT(c.x*(1-mid) + a.x*mid, c.y*(1-mid) + a.y*mid);
        la = dist(b, c);
        lb = dist(b, h);
        lc = dist(b, s);
        if (la+lb<=t2 && la+lc<=t1) l = mid;
        else r = mid;
    }
    b = POINT(c.x*(1-l) + a.x*l, c.y*(1-l) + a.y*l);
    return dist(b, c);
}
int main() {

    cin >>t1>>t2>>c.x>>c.y>>h.x >> h.y >> s.x>> s.y;
    double la, lb, lc;
    la = dist(c, s);
    lb = dist(c, h);
    lc = dist(s, h);

    if (lb + t2 >= la + lc) {
        printf("%.10lf
", min(lb+t2, la+lc+t1));
        return 0;
    }
    t1 += la + 1e-10;
    t2 += lb + 1e-10;

    double l = 0, r = 1, lm, rm, ans = 0, v1, v2;
    for (int i=0; i<300; i++) {
        lm = (2*l + r)/3.0, rm = (2*r + l)/3.0;
        v1 = calc(lm), v2 = calc(rm);
        ans = max(ans, max(v1, v2));
        if (v1 < v2) l = lm;
        else r = rm;
    }

    printf("%.10lf
", ans);

    return 0;
}


原文地址:https://www.cnblogs.com/aukle/p/3220213.html