• codeforces 8D Two Friends 二分+ 判断三个圆是否有公共交点


    题目链接

    有两个人x, y, 现在在A点, x要直接去B点, y要先去C点在去B点, 现在给出x, y两人可以行走的最大距离T1, T2, 求出他们从A点出发之后, 可以走的最长的公共路径。

    我们先看最特殊的情况, T1超级大, 所以x可以先走到C点在到B点, 这种情况的最长距离为min(T1, T2)。

    然后看一般情况。 现在, x先陪y向C的方向走一段, 然后在走回B点。

    我们二分走的这一段的距离。

    假设距离为m, 那么我们发现, 他们两人分开的那个点, 在以A为圆心, m为半径的圆内。 同时也在以B为圆心, 半径为T1-m的圆内。 同时也在以C为圆心, T2-bc-m的圆内, bc是B C两点之间的距离。  具体的话可以画画图, 很容易看出来。

    现在的问题就是看这三个圆有没有公共交点。

    代码我抄的cf上面的..

    #include<cstdio>
    #include<cmath>
    #include<complex>
    #include<algorithm>
    
    using namespace std;
    
    #define point complex<double>
    
    const double eps = 1e-7;
    
    double t1, t2;
    point c, a, b;
    
    void readpoint(point &p) {
      double x, y;
      scanf("%lf %lf", &x, &y);
      p = point(x, y);
    }
    
    bool inter(point a, double r_a, point b, double r_b, point c, double r_c) { //以c为主圆求a b焦点判相交
      if (abs(c - a) <= r_a && abs(c - b) <= r_b) return true;
      b -= a; c -= a; //以a为原点
      point r = point(b.real() / abs(b), b.imag() / abs(b)); //将x轴正方向置为b
      b /= r; c /= r;
      double d = (r_a * r_a - r_b * r_b + abs(b) * abs(b)) / (2 * abs(b));
      double h = sqrt(max(r_a * r_a - d * d, 0.0));
      if (abs(h * h + (d - abs(b)) * (d - abs(b))) - r_b * r_b > eps) return false;
      if (abs(point(d, h) - c) <= r_c || abs(point(d, -h) - c) <= r_c) return true;
      return false;
    }
    
    bool check(point a, double r_a, point b, double r_b, point c, double r_c) { //判断三圆是否相交
      if (r_a <= eps || r_b <= eps || r_c <= eps) return false; //有空集
      if (inter(a, r_a, c, r_c, b, r_b)) return true;
      if (inter(b, r_b, a, r_a, c, r_c)) return true;
      if (inter(c, r_c, b, r_b, a, r_a)) return true;
      return false;
    }
    
    int main() {
        scanf("%lf %lf", &t2, &t1);
        readpoint(a); readpoint(b); readpoint(c);
        double T1 = t1+abs(a-b), T2 = t2+abs(a-c)+abs(c-b);
        if(T1>=abs(a-c)+abs(b-c)) {
            printf("%.5f
    ", min(T1, T2));
            return 0;
        }
        double l = 0, r = min(T2, T1);
        while(fabs(r-l)>eps) {
            double m = (l+r)/2;
            if(check(a, m, b, T1-m, c, T2-abs(b-c)-m))
                l = m;
            else
                r = m;
        }
        printf("%.6f
    ", l);
        return 0;
    }
  • 相关阅读:
    P1030 求先序排列 P1305 新二叉树
    spfa
    Clairewd’s message ekmp
    Cyclic Nacklace hdu3746 kmp 最小循环节
    P1233 木棍加工 dp LIS
    P1052 过河 线性dp 路径压缩
    Best Reward 拓展kmp
    Period kmp
    Substrings kmp
    Count the string kmp
  • 原文地址:https://www.cnblogs.com/yohaha/p/5275935.html
Copyright © 2020-2023  润新知