XVII Open Cup named after E.V. Pankratiev. GP of Tatarstan B. White Triangle

抄lrj的板子抄错了gg,然后还要顺时针输出,没了

计算几何板子++

圆的切线

#include <bits/stdc++.h>
using namespace std;
typedef double db;
const db EPS = 1e-6;
int sgn(db x) {
    return x < -EPS ? -1 : EPS < x;
}
struct Poi {
    db x, y;
    Poi() {}
    Poi(db x, db y):x(x), y(y) {}
    db cross(const Poi&rhs) {
        return x * rhs.y - y * rhs.x;
    }
    db dot(const Poi&rhs) {
        return x * rhs.x + y * rhs.y;
    }
    db len2() {
        return dot(*this);
    }
    Poi operator + (const Poi&rhs) {
        return Poi(x + rhs.x, y + rhs.y);
    }
    Poi operator - (const Poi&rhs) {
        return Poi(x - rhs.x, y - rhs.y);
    }
    Poi operator * (db p) {
        return Poi(x * p, y * p);
    }
    Poi operator / (db p) {
        return Poi(x / p, y / p);
    }
    bool operator == (const Poi&rhs) {
        return sgn(x - rhs.x) == 0 && sgn(y - rhs.y) == 0;
    }
    Poi norm() {
        return Poi(-y, x);
    }
    db ang() {
        db a = atan2(y, x);
        if (a < 0) a += M_PI * 2;
        return a;
    }
};
struct Cir:Poi {
    db r;
    Cir() {}
    Cir(db _x, db _y, db r):r(r) {
        x = _x, y = _y;
    }
    Poi getPoi(db ang) {
        return Poi(x + cos(ang) * r, y + sin(ang) * r);
    }
};
int getTangents(Cir A, Cir B, Poi*a, Poi*b) {
    int cnt = 0;
    if (A.r < B.r) { swap(A, B), swap(a, b); }
    db d2 = (A - B).len2();
    db rdiff = A.r - B.r;
    db rsum = A.r + B.r;
    if (d2 < rdiff * rdiff) return 0;
    
    db base = (B - A).ang();
    if (sgn(d2) == 0 && sgn(A.r - B.r) == 0) return -1;

    if (sgn(d2 - rdiff * rdiff) == 0) {
        a[cnt] = A.getPoi(base); b[cnt] = B.getPoi(base); ++cnt;
        return 1;
    }

    db ang = acos((A.r - B.r) / sqrt(d2));
    a[cnt] = A.getPoi(base + ang); b[cnt] = B.getPoi(base + ang); ++cnt;
    a[cnt] = A.getPoi(base - ang); b[cnt] = B.getPoi(base - ang); ++cnt;
    if (sgn(d2 - rsum * rsum) == 0) {
        a[cnt] = A.getPoi(base); b[cnt] = B.getPoi(M_PI + base); ++cnt;
    } else if (sgn(d2 - rsum * rsum) > 0) {
        ang = acos((A.r + B.r) / sqrt(d2));
        a[cnt] = A.getPoi(base + ang); b[cnt] = B.getPoi(M_PI + base + ang); ++cnt;
        a[cnt] = A.getPoi(base - ang); b[cnt] = B.getPoi(M_PI + base - ang); ++cnt;
    }

    return cnt;
}

bool inTriangle(Poi x, Poi a, Poi b, Poi c) {
    int s0, s1, s2;
    s0 = sgn((a - x).cross(b - x));
    s1 = sgn((b - x).cross(c - x));
    s2 = sgn((c - x).cross(a - x));
    return s0 == s1 && s1 == s2;
}

int getLineInter(Poi a, Poi b, Poi c, Poi d, Poi&i) {
    b = b - a, d = d - c;
    Poi u = a - c;
    db e = b.cross(d);
    if (sgn(e) == 0) return 0;
    db t = d.cross(u) / e;
    i = a + b * t;
    return 1;
}

bool isInteger(db x) {
    return sgn(x - floor(x)) == 0 || sgn(x - ceil(x)) == 0;
}

Poi A, B;
Cir cirA[3], cirB[3];
db dA[3], dB[3];
bool inA, inB;

struct Tag {
    Poi a[4], b[4];
    int cnt;
} tagLine[3];

db disToLine(Poi p, Poi a, Poi b) {
    Poi v1 = b - a, v2 = p - a;
    return fabs(v1.cross(v2)) / sqrt(v1.len2());
}

bool ok(Poi x, Poi y, Poi z) {
    if (sgn(disToLine(A, x, y) - fabs(dA[0])) != 0)
        return false;
    if (sgn(disToLine(A, y, z) - fabs(dA[1])) != 0)
        return false;
    if (sgn(disToLine(A, x, z) - fabs(dA[2])) != 0)
        return false;
    if (sgn(disToLine(B, x, y) - fabs(dB[0])) != 0)
        return false;
    if (sgn(disToLine(B, y, z) - fabs(dB[1])) != 0)
        return false;
    if (sgn(disToLine(B, x, z) - fabs(dB[2])) != 0)
        return false;
    if (sgn((y - x).cross(z - x)) > 0)
        return false;
    printf("%.10lf %.10lf\n", x.x, x.y);
    printf("%.10lf %.10lf\n", y.x, y.y);
    printf("%.10lf %.10lf\n", z.x, z.y);
    return true;
}

bool isSolved(int a, int b, int c) {
    Poi p, q, o;
    if (!getLineInter(tagLine[0].a[a], tagLine[0].b[a],
                      tagLine[1].a[b], tagLine[1].b[b],
                      p))
        return false;
    if (!getLineInter(tagLine[1].a[b], tagLine[1].b[b],
                      tagLine[2].a[c], tagLine[2].b[c],
                      q))
        return false;
    if (!getLineInter(tagLine[2].a[c], tagLine[2].b[c],
                      tagLine[0].a[a], tagLine[0].b[a],
                      o))
        return false;
    if (inA != inTriangle(A, p, q, o)
    ||  inB != inTriangle(B, p, q, o))
        return false;
    //printf("%.12lf %.12lf\n", o.x, o.y);
    //printf("%.12lf %.12lf\n", p.x, p.y);
    //printf("%.12lf %.12lf\n", q.x, q.y);
    //puts("");
    if (ok(p, q, o)) return true;
    if (ok(p, o, q)) return true;
    if (ok(q, p, o)) return true;
    if (ok(q, o, p)) return true;
    if (ok(o, p, q)) return true;
    if (ok(o, q, p)) return true;
    
    //if (isInteger(p.x) && isInteger(p.y)
    //&&  isInteger(q.x) && isInteger(q.y)
    //&&  isInteger(o.x) && isInteger(o.y)) {
    //  
    //  
    //  
    //  return true;
    //}
    return false;
}

int main() {

#ifdef lol
    freopen("b.in", "r", stdin);
    freopen("b.out", "w", stdout);
#endif

    inA = inB = true;
    scanf("%lf%lf", &A.x, &A.y);
    for (int i = 0; i < 3; ++i) {
        scanf("%lf", &dA[i]);
        cirA[i] = Cir(A.x, A.y, fabs(dA[i]));
    }
    if (dA[0] < 0) inA = false;

    scanf("%lf%lf", &B.x, &B.y);
    for (int i = 0; i < 3; ++i) {
        scanf("%lf", &dB[i]);
        cirB[i] = Cir(B.x, B.y, fabs(dB[i]));
    }
    if (dB[0] < 0) inB = false;

    //printf("%d\n", ok(Poi(0, 0), Poi(0, 12), Poi(16, 0)));
    //return 0;
    for (int j = 0; j < 3; ++j) {
        tagLine[j].cnt = getTangents(cirA[j], cirB[j], tagLine[j].a, tagLine[j].b);
        for (int i = 0; i < tagLine[j].cnt; ++i) {
            if (tagLine[j].a[i] == tagLine[j].b[i]) {
                tagLine[j].b[i] = tagLine[j].a[i] + (tagLine[j].a[i] - A).norm();
            }
        }
    }
    for (int a = 0; a < tagLine[0].cnt; ++a) {
        for (int b = 0; b < tagLine[1].cnt; ++b) {
            for (int c = 0; c < tagLine[2].cnt; ++c) {
                if (isSolved(a, b, c)) {
                //    puts("");
                //    continue;
                    return 0;
                }
            }
        }
    }
    

    return 0;
}

 

posted @ 2017-10-09 09:59  ichneumon  阅读(177)  评论(0编辑  收藏  举报