欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【UVa 12304】2D Geometry 110 in 1! (计算几何、圆)

程序员文章站 2022-04-02 16:56:00
...

Description

https://vjudge.net/problem/UVA-12304

Solution

都是一些最基本的操作,没什么技术含量,只是代码量有点大,,码了一天,摆上代码吧。

Source

/************************************************
 * Happy Spring Festival!
 * Au: Hany01
 * Date: Feb 11th, 2018
 * Prob: UVa12304 2D Geometry 110 in 1!
 * Email: [email protected]
************************************************/

#include<bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;

#define rep(i, j) for (register int i = 0, i##_end_ = (j); i < i##_end_; ++ i)
#define For(i, j, k) for (register int i = (j), i##_end_ = (k); i <= i##_end_; ++ i)
#define Fordown(i, j, k) for (register int i = (j), i##_end_ = (k); i >= i##_end_; -- i)
#define Set(a, b) memset(a, b, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define fir first
#define sec second
#define pb(a) push_back(a)
#define mp(a, b) make_pair(a, b)
#define ALL(a) (a).begin(), (a).end()
#define SZ(a) ((int)(a).size())
#define INF (0x3f3f3f3f)
#define INF1 (2139062143)
#define Mod (1000000007)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define y1 wozenmezhemecaia

template <typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
template <typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }

inline int read()
{
    register int _, __; register char c_;
    for (_ = 0, __ = 1, c_ = getchar(); c_ < '0' || c_ > '9'; c_ = getchar()) if (c_ == '-') __ = -1;
    for ( ; c_ >= '0' && c_ <= '9'; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48);
    return _ * __;
}

inline void File()
{
#ifdef hany01
    freopen("uva12304.in", "r", stdin);
    freopen("uva12304.out", "w", stdout);
#endif
}

const double eps = 1e-7, Pi = acos(-1.0);

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

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 - (Vector A, Vector B) {
    return Vector(A.x - B.x, A.y - B.y);
}

Vector operator * (Vector A, double p) {
    return Vector(A.x * p, A.y * p);
}

Vector operator / (Vector A, double p) {
    return Vector(A.x / p, A.y / p);
}

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

bool operator < (const Vector& A, const Vector& B) {
    return A.x < B.x || (A.x == B.x && A.y < B.y);
}

struct Circle
{
    Point O; double r;
    Circle(Point O = Point(0, 0), double r = 0): O(O), r(r) {}
    Point point(double rad) {
        return Point(O.x + cos(rad) * r, O.y + sin(rad) * r);
    }
};

Point Mid(Point A, Point B) {
    return Point((A.x + B.x) / 2, (A.y + B.y) / 2);
}

double Cross(Point A, Point B) {
    return A.x * B.y - A.y * B.x;
}

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

double Length(Vector A) {
    return sqrt(Dot(A, A));
}

double Angle(Vector A, Vector B) {
    return acos(Dot(A, B) / Length(A) / Length(B));
}

double Angle(Vector A) {
    return atan2(A.y, A.x);
}

Point GetLineIntersection(Point P, Vector v, Point Q, Vector w) {
    register Vector u = P - Q;
    return P + v * (Cross(w, u) / Cross(v, w));
}

Point GetLineProjection(Point P, Point A, Point B) {
    Vector v = B - A;
    return A + v * (Dot(v, P - A) / Dot(v, v));
}

Vector Rotate(Vector A, double rad) {
    return Vector(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad));
}

double DistanceToLine(Point P, Point A, Point B) {
    return fabs(Cross(P - A, B - A)) / Length(B - A);
}

inline void Correct(double& x) {
    while (dcmp(x) < 0) x += Pi;
    while (dcmp(x - Pi) >= 0) x -= Pi;
}

int GetTangents(Circle C, Point P, double* Ans) {
    double d = Length(C.O - P);
    if (dcmp(d - C.r) < 0) return 0;
    double aPC = Angle(P - C.O), theta = acos(C.r / d);
    Ans[1] = aPC + theta + Pi / 2, Ans[2] = aPC - theta + Pi / 2;
    Correct(Ans[1]), Correct(Ans[2]);
    if (!dcmp(Ans[1] - Ans[2])) return 1;
    return 2;
}

int GetLineCircleIntersection(Point A, Point B, Circle C, Point& S1, Point& S2) {
    double d = DistanceToLine(C.O, A, B);
    register int tmp = dcmp(d - C.r);
    if (tmp > 0) return 0;
    Point P = GetLineProjection(C.O, A, B);
    if (!tmp) { S1 = S2 = P; return 1; }
    double L = sqrt(C.r * C.r - d * d);
    Vector v = (B - A) / Length(B - A);
    S1 = P - v * L, S2 = P + v * L;
    return 2;
}

int GetCircleIntersection(Circle C1, Circle C2, Point& P1, Point& P2) {
    double d = Length(C1.O - C2.O);
    if (!dcmp(d)) { if (!dcmp(C1.r - C2.r)) return -1; return 0; }
    if (dcmp(C1.r + C2.r - d) < 0 || dcmp(fabs(C1.r - C2.r) - d) > 0) return 0;
    double a = Angle(C2.O - C1.O), da = acos((C1.r * C1.r + d * d - C2.r * C2.r) / (2 * C1.r * d));
    P1 = C1.point(a - da), P2 = C1.point(a + da);
    if (P1 == P2) return 1;
    return 2;
}

Point move(Point A, double a, double r) { return Point(A.x, A.y + r / cos(a)); }

char Q[40];

int main()
{
    File();
    while (scanf("%s", Q) != EOF)
    {
        if (Q[4] == 'u')
        {
            register Point A, B, C, D, E, vDO, vEO, O;
            register double r;
            scanf("%lf%lf%lf%lf%lf%lf", &A.x, &A.y, &B.x, &B.y, &C.x, &C.y);
            D = Mid(B, C);
            vDO = Vector(B.y - C.y, C.x - B.x),
            E = Mid(A, C);
            vEO = Vector(A.y - C.y, C.x - A.x);
            O = GetLineIntersection(D, vDO, E, vEO), r = Length(O - A);
            printf("(%.6lf,%.6lf,%.6lf)\n", O.x, O.y, r);
        }
        else if (Q[0] == 'I')
        {
            register Point A, B, C, D, E, vBD, vCE, O;
            register double r, ABD, ACE;
            scanf("%lf%lf%lf%lf%lf%lf", &A.x, &A.y, &B.x, &B.y, &C.x, &C.y);
            if (dcmp(Cross(B - A, C - A)) < 0) swap(B, C);
            ABD = Angle(A - B, C - B) / 2;
            ACE = Angle(A - C, B - C) / 2;
            vBD = Rotate(C - B, ABD);
            vCE = Rotate(B - C, 2 * Pi - ACE);
            O = GetLineIntersection(B, vBD, C, vCE);
            r = DistanceToLine(O, A, B);
            printf("(%.6lf,%.6lf,%.6lf)\n", O.x, O.y, r);
        }
        else if (Q[0] == 'T')
        {
            register Circle C;
            register Point P;
            register double Ans[6];
            register int cnt;
            scanf("%lf%lf%lf%lf%lf", &C.O.x, &C.O.y, &C.r, &P.x, &P.y);
            cnt = GetTangents(C, P, Ans);
            if (!cnt) { puts("[]"); continue; }
            sort(Ans + 1, Ans + 1 + cnt);
            putchar('[');
            For(i, 1, cnt - 1) printf("%.6lf,", Ans[i] / Pi * 180);
            printf("%.6lf]\n", Ans[cnt] / Pi * 180);
        }
        else if (Q[13] == 'A')
        {
            register Point P, A, B, A1, A2, A3;
            register double r, d, a;
            register Circle C;
            register int cntt;
            scanf("%lf%lf%lf%lf%lf%lf%lf", &P.x, &P.y, &A.x, &A.y, &B.x, &B.y, &r);
            if (!dcmp((d = DistanceToLine(P, A, B)) - r * 2))
            {
                A1 = GetLineProjection(P, A, B);
                printf("[(%lf,%lf)]\n", (A1.x + P.x) / 2, (A1.y + P.y) / 2);
                continue;
            }
            if (dcmp(d - r * 2) > 0) { puts("[]"); continue; }
            C = Circle(P, r);
            a = Angle(B - A);
            if (!(cntt = GetLineCircleIntersection(move(A, a, r), move(B, a, r), C, A1, A2))) {
                cntt = GetLineCircleIntersection(move(A, a, -r), move(B, a, -r), C, A1, A2);
            }
            else if (cntt == 1) GetLineCircleIntersection(move(A, a, -r), move(B, a, -r), C, A2, A3);
            if (A2 < A1) swap(A1, A2);
            printf("[(%.6lf,%.6lf),(%.6lf,%.6lf)]\n", A1.x, A1.y, A2.x, A2.y);
        }
        else if (Q[18] == 'L')
        {
            register Point Ans[6], A1, A2, B1, B2, A1_, VA, B1_, VB;
            register double a1, a2, r;
            register int cnt = 0;
            scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf", &A1.x, &A1.y, &A2.x, &A2.y, &B1.x, &B1.y, &B2.x, &B2.y, &r);
            a1 = Angle(A2 - A1);
            a2 = Angle(B2 - B1);
            For(i, -1, 1) if (i) For(j, -1, 1) if (j) {
                A1_ = move(A1, a1, r * i);
                VA = A2 - A1;
                B1_ = move(B1, a2, r * j);
                VB = B2 - B1;
                Ans[++ cnt] = GetLineIntersection(A1_, VA, B1_, VB);
            }
            sort(Ans + 1, Ans + 5);
            putchar('[');
            For(i, 1, 4) printf("(%.6lf,%.6lf)%c", Ans[i].x, Ans[i].y, i == 4 ? ']' : ',');
            putchar('\n');
        } else if (Q[18] == 'D') {
            register Circle C1, C2;
            register Point Ans1, Ans2;
            register double r;
            register int cnt;
            scanf("%lf%lf%lf", &C1.O.x, &C1.O.y, &C1.r),
            scanf("%lf%lf%lf", &C2.O.x, &C2.O.y, &C2.r);
            scanf("%lf", &r), C1.r += r, C2.r += r;
            cnt = GetCircleIntersection(C1, C2, Ans1, Ans2);
            if (!cnt) puts("[]");
            else if (cnt == 1)
                printf("[(%lf,%lf)]\n", Ans1.x, Ans1.y);
            else
            {
                if (Ans2 < Ans1) swap(Ans1, Ans2);
                printf("[(%lf,%lf),(%lf,%lf)]\n", Ans1.x, Ans1.y, Ans2.x, Ans2.y);
            }
        }
    }
    return 0;
}