Machining Disc Rotors Gym - 101955L(计算几何)

Machining Disc Rotors Gym - 101955L

题意:有一个圆心为\((0,0)\)的大圆被\(n\)个互不相交的圆切割(下图阴影部分为割掉的面积)。保证\(n\)个圆中不会有某个包含整个大圆的情况。问切割后大圆剩余部分的直径(多边形上两点最远距离)。

题解:显然剩余部分的直径是以下两种之一:

  • 原本大圆的直径。
  • 两个交点的距离。

如何判断是否存在直径呢?我们可以把每一个交点关于圆心作对称点,如果有一个对称点都不在\(n\)个圆内,说明这个点与对称点构成了一条没有被切掉的直径。若没有则是两交点之间的最大距离。

#include <bits/stdc++.h>
#define fopi freopen("in.txt", "r", stdin)
#define fopo freopen("out.txt", "w", stdout)
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
const double eps = 1e-10;
const int maxn = 1000 + 10;

struct Point{
    double x,y;
    Point(double x=0,double y=0):x(x),y(y){}
};
typedef Point Vector;
Vector operator + (Vector A,Vector B){
    return Vector(A.x+B.x,A.y+B.y);
}
Vector operator - (Point A,Point B){
    return Vector(A.x-B.x,A.y-B.y);
}
Vector operator * (Point A,double p){
    return Vector(A.x*p,A.y*p);
}

int dcmp(double x) { return fabs(x) < eps ? 0 : (x < 0 ? -1 : 1); }
bool operator == (const Point& a,const Point& b){
    return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}

double Dot(Vector A,Vector B){
    return A.x*B.x+A.y*B.y;
}
double Length(Vector A){
    return sqrt(Dot(A,A));
}

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

double angle(Vector v) {
    return atan2(v.y, v.x);
}

//Circle and Circle intersection
int CCIntersection(Circle C1,Circle C2,vector<Point>& sol){
    double d=Length(C1.c-C2.c);
    if(dcmp(d)==0){
        if(dcmp(C1.r-C2.r)==0)return -1;
        return 0;
    }
    if(dcmp(C1.r+C2.r-d)<0)return 0;
    if(dcmp(fabs(C1.r-C2.r)-d)>0)return 0;

    double a=angle(C2.c-C1.c);
    double da=acos((C1.r*C1.r+d*d-C2.r*C2.r)/(2*C1.r*d));

    Point p1=C1.point(a-da),p2=C1.point(a+da);

    sol.push_back(p1);
    if(p1==p2)return 1;
    sol.push_back(p2);
    return 2;
}

bool PinC(Point p, Circle c) { //Point in Circle
    double dist = Length(p-c.c);
    return dcmp(dist-c.r) < 0;
}


int T, n;
double r;
Circle a[maxn];
vector<Point> sect, k;

bool check() {
    if (sect.empty()) return true;
    for (auto p : sect) {
        bool flag = true;
        Point p1 = {-p.x, -p.y};
        for (int i = 1; i <= n; i++)
            if (PinC(p1, a[i])) {
                flag = false;
                break;
            }
        if (flag) return true;
    }
    return false;
 }

int main() {
    scanf("%d", &T);
    for (int ca = 1; ca <= T; ca++) {
        sect.clear();
        scanf("%d%lf", &n, &r);
        Circle mid = {{0,0}, r};
        Point p1, p2;
        for (int i = 1; i <= n; i++) {
            int x, y, z;
            scanf("%d%d%d", &x, &y, &z);
            a[i] = {{x, y}, z};
            CCIntersection(a[i], mid, sect);
        }
        double ans = 0, tmp;
        for (int i = 0; i < sect.size(); i++)
            for (int j = i+1; j < sect.size(); j++) {
                if ((tmp = Length(sect[i]-sect[j])) > ans) ans = tmp;
            }
        printf("Case #%d: %.15f\n", ca, check() ? 2*r : ans);
    }
}
posted @ 2019-08-16 20:33  jvruodejrLS  阅读(472)  评论(0编辑  收藏  举报

Contact with me