【题意】有两个人AlanBob,他们现在都在A点,现在Bob想去B点,Alan想先到C点再去B点。Alan所走的总路程不能超过T1Bob所走的总路程不能超过T2。求他们从A出发到第一次分开所能走的最长的公共路程。

【解题方法】参考XHR神牛的论文AC。

【AC代码】

//
//Created by just_sort 2016/12/8
//Copyright (c) 2016 just_sort.All Rights Reserved
//

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
using namespace std;
using namespace __gnu_pbds;
typedef long long LL;
typedef pair<int, LL> pp;
#define MP(x,y) make_pair(x,y)
const int maxn = 400020;
const int maxm = 1<<12;
const int inf = 0x3f3f3f3f;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>order_set;
//head

typedef long double LD;
const LD eps = 1e-10;

int dcmp(LD x) {
    if(fabs(x) < eps) return 0;
    return x < 0 ? -1 : 1;
}

LD sqr(LD x) { return x * x; }

struct Point
{
    LD x, y;
    Point(LD x = 0, LD y = 0):x(x), y(y) {}
    void read() { cin >> x >> y; }
};

Point operator - (const Point& A, const Point& B) {
    return Point(A.x - B.x, A.y - B.y);
}

bool operator == (const Point& A, const Point& B) {
    return dcmp(A.x - B.x) == 0 && dcmp(A.y - B.x) == 0;
}

LD Dot(const Point& A, const Point& B) {
    return A.x * B.x + A.y * B.y;
}

LD Length(const Point& A) { return sqrt(Dot(A, A)); }

LD angle(const Point& A) { return atan2(A.y, A.x); }

struct Circle
{
    Point c;
    LD r;
    Circle() {}
    Circle(Point c, LD r):c(c), r(r) {}
    Point point(LD a) {
        return Point(c.x + cos(a) * r, c.y + sin(a) * r);
    }
};

LD t1, t2, T1, T2;
Point p[3];
Circle o[3];
vector<Point> sol;

bool OnCircle(Point p, Circle C) {
    return dcmp(Length(p - C.c) - C.r) == 0;
}

bool getCirclesolsection(Circle C1, Circle C2) {
    LD &r1 = C1.r, &r2 = C2.r;
    LD &x1 = C1.c.x, &x2 = C2.c.x, &y1 = C1.c.y, &y2 = C2.c.y;
    LD d = Length(C1.c - C2.c);
    if(dcmp(fabs(r1-r2) - d) > 0) return true;
    if(dcmp(r1 + r2 - d) < 0) return false;
    LD d2 = Dot(C1.c - C2.c, C1.c - C2.c);
    LD a = r1*(x1-x2)*2, b = r1*(y1-y2)*2, c = r2*r2-r1*r1-d*d;
    LD p = a*a+b*b, q = -a*c*2, r = c*c-b*b;

    LD cosa, sina, cosb, sinb;
    //One solsection
    if(dcmp(d - (r1 + r2)) == 0 || dcmp(d - fabs(r1 - r2)) == 0) {
        cosa = -q / p / 2;
        sina = sqrt(1 - sqr(cosa));
        Point p(x1 + C1.r * cosa, y1 + C1.r * sina);
        if(!OnCircle(p, C2)) p.y = y1 - C1.r * sina;
        sol.push_back(p);
        return true;
    }
    //Two solsections
    LD delta = sqrt(q * q - p * r * 4);
    cosa = (delta - q) / p / 2;
    cosb = (-delta - q) / p / 2;
    sina = sqrt(1 - sqr(cosa));
    sinb = sqrt(1 - sqr(cosb));
    Point p1(x1 + C1.r * cosa, y1 + C1.r * sina);
    Point p2(x1 + C1.r * cosb, y1 + C1.r * sinb);
    if(!OnCircle(p1, C2)) p1.y = y1 - C1.r * sina;
    if(!OnCircle(p2, C2)) p2.y = y1 - C1.r * sinb;
    if(p1 == p2)  p1.y = y1 - C1.r * sina;
    sol.push_back(p1);
    sol.push_back(p2);
    return true;
}

bool Include(Circle C1, Circle C2) {
    LD d = Length(C1.c - C2.c);
    if(dcmp(fabs(C1.r-C2.r) - d) > 0) return true;
    return false;
}

bool InAllCircle(const Point& t) {
    for(int i = 0; i < 3; i++) {
        LD d = Length(t - o[i].c);
        if(dcmp(d - o[i].r) > 0) return false;
    }
    return true;
}

//判断3个圆是否有交
bool check() {
    sol.clear();
    for(int i = 0; i < 3; i++)
        for(int j = i + 1; j < 3; j++)
            if(!getCirclesolsection(o[i], o[j])) return false;
    for(int i = 0; i < 3; i++)
        for(int j = i + 1; j < 3; j++)
            if(Include(o[i], o[j])) return true;
    for(Point t : sol)
        if(InAllCircle(t)) return true;
    return false;
}

int main()
{
    cin>>t1>>t2;
    for(int i = 0; i < 3; i++) p[i].read();
    LD AB = Length(p[1] - p[0]);
    LD AC = Length(p[2] - p[0]);
    LD BC = Length(p[2] - p[1]);
    T1 = AC + BC + t1;
    T2 = AB + t2;
    if(dcmp(T2 - AC - BC) >= 0){
        LD ans = min(T1, T2);
        printf("%.10Lf\n", ans);
        return 0;
    }
    LD l = 0, r = min(T1 - BC, T2);
    for(int i = 0; i < 100; i++){
        LD mid = (l + r) / 2.0;
        o[0] = Circle(p[0], mid);
        o[1] = Circle(p[1], T2 - mid);
        o[2] = Circle(p[2], T1 - BC - mid);
        if(check()) l = mid;
        else r = mid;
    }
    printf("%.10Lf\n", l);
    return 0;
}