zoukankan      html  css  js  c++  java
  • Uva 12304

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3726

    题意:

    新白书p267,  有说

    给出三角形三点求外接圆,内接圆,给出一点求以及圆求过该点的切线, 给出一直线和一个点求过该点与直线想切的圆,圆半径给出。给出两条相交的直线求与这两条直线想切的圆, 给出两个相离的圆,求与这两个圆都想切的圆

    思路:

      其实没什么很难的就是模板运用,还要注意细节什么的,这题考了很多二维几何的模板,值得一做,话说这是做ACM 题目以来写的最长的题目。细心。。

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    #include <string>
    #include <set>
    #include <functional>
    #include <numeric>
    #include <sstream>
    #include <stack>
    #include <map>
    #include <queue>
    
    #define CL(arr, val) memset(arr, val, sizeof(arr))
    
    #define lc l,m,rt<<1
    #define rc m + 1,r,rt<<1|1
    #define PI acos(-1.0)
    #define L(x)    (x) << 1
    #define R(x)    (x) << 1 | 1
    #define MID(l, r)   (l + r) >> 1
    #define Min(x, y)   (x) < (y) ? (x) : (y)
    #define Max(x, y)   (x) < (y) ? (y) : (x)
    #define E(x)        (1 << (x))
    #define iabs(x)     (x) < 0 ? -(x) : (x)
    #define OUT(x)  printf("%I64d
    ", x)
    #define lowbit(x)   (x)&(-x)
    #define Read()  freopen("data.in", "r", stdin)
    #define Write() freopen("d.out", "w", stdout)
    #define ll unsigned long long
    
    
    #define M 100007
    #define N 65736
    
    using namespace std;
    
    const int inf = 0x7f7f7f7f;
    const int mod = 1000000007;
    const double eps = 1e-6;
    
    
    struct Point
    {
        double x,y;
        Point(double tx = 0,double ty = 0) : x(tx),y(ty){}
    };
    typedef Point Vtor;
    //向量的加减乘除
    Vtor operator + (Vtor A,Vtor B) { return Vtor(A.x + B.x,A.y + B.y); }
    Vtor operator - (Point A,Point B) { return Vtor(A.x - B.x,A.y - B.y); }
    Vtor operator * (Vtor A,double p) { return Vtor(A.x*p,A.y*p); }
    Vtor operator / (Vtor A,double p) { return Vtor(A.x/p,A.y/p); }
    bool operator < (Point A,Point B) { return A.x < B.x || (A.x == B.x && A.y < B.y);}
    int dcmp(double x){ if (fabs(x) < eps) return 0; else return x < 0 ? -1 : 1; }
    bool operator == (Point A,Point B) {return dcmp(A.x - B.x) == 0 && dcmp(A.y - B.y) == 0; }
    //向量的点积,长度,夹角
    double Dot(Vtor A,Vtor B) { return (A.x*B.x + A.y*B.y); }
    double Length(Vtor A) { return sqrt(Dot(A,A)); }
    double Angle(Vtor A,Vtor B) { return acos(Dot(A,B)/Length(A)/Length(B)); }
    //叉积,三角形面积
    double Cross(Vtor A,Vtor B) { return A.x*B.y - A.y*B.x; }
    double Area2(Point A,Point B,Point C) { return Cross(B - A,C - A); }
    //向量的旋转,求向量的单位法线(即左转90度,然后长度归一)
    Vtor Rotate(Vtor A,double rad){ return Vtor(A.x*cos(rad) - A.y*sin(rad),A.x*sin(rad) + A.y*cos(rad)); }
    Vtor Normal(Vtor A)
    {
        double L = Length(A);
        return Vtor(-A.y/L, A.x/L);
    }
    //直线的交点
    Point GetLineIntersection(Point P,Vtor v,Point Q,Vtor w)
    {
        Vtor u = P - Q;
        double t = Cross(w,u)/Cross(v,w);
        return P + v*t;
    }
    //点到直线的距离
    double DistanceToLine(Point P,Point A,Point B)
    {
        Vtor v1 = B - A;
        return fabs(Cross(P - A,v1))/Length(v1);
    }
    //点到线段的距离
    double DistanceToSegment(Point P,Point A,Point B)
    {
        if (A == B) return Length(P - A);
        Vtor v1 =  B - A , v2 = P - A, v3 = P - B;
        if (dcmp(Dot(v1,v2)) < 0) return Length(v2);
        else if (dcmp(Dot(v1,v3)) > 0) return Length(v3);
        else return fabs(Cross(v1,v2))/Length(v1);
    }
    //点到直线的映射
    Point GetLineProjection(Point P,Point A,Point B)
    {
        Vtor v = B - A;
        return A + v*Dot(v,P - A)/Dot(v,v);
    }
    
    //判断线段是否规范相交
    bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2)
    {
        double c1 = Cross(a2 - a1,b1 - a1), c2 = Cross(a2 - a1,b2 - a1),
               c3 = Cross(b2 - b1,a1 - b1), c4 = Cross(b2 - b1,a2 - b1);
        return dcmp(c1)*dcmp(c2) < 0 && dcmp(c3)*dcmp(c4) < 0;
    }
    //判断点是否在一条线段上
    bool OnSegment(Point P,Point a1,Point a2)
    {
        return dcmp(Cross(a1 - P,a2 - P)) == 0 && dcmp(Dot(a1 - P,a2 - P)) < 0;
    }
    //多边形面积
    double PolgonArea(Point *p,int n)
    {
        double area = 0;
        for (int i = 1; i < n - 1; ++i)
        area += Cross(p[i] - p[0],p[i + 1] - p[0]);
        return area/2;
    }
    
    struct Line
    {
        Point p,b;
        Vtor v;
        Line(){}
        Line(Point a,Point b,Vtor v) : p(a),b(b),v(v) {}
        Line(Point p,Vtor v) : p(p),v(v){}
        Point point(double t) { return p + v*t; }
    };
    struct Circle
    {
        Point c;
        double r;
        Circle(Point tc,double tr) : c(tc),r(tr){}
        Point point(double a)
        {
            return Point(c.x + cos(a)*r,c.y + sin(a)*r);
        }
    };
    //判断圆与直线是否相交以及求出交点
    int getLineCircleIntersection(Line L,Circle C,double &t1,double &t2,vector<Point> &sol)
    {
    //    printf(">>>>>>>>>>>>>>>>>>>>>>>>
    ");
        //注意sol没有清空哦
        double a = L.v.x, b = L.p.x - C.c.x, c = L.v.y, d = L.p.y - C.c.y;
        double e = a*a + c*c , f = 2*(a*b + c*d),  g = b*b + d*d - C.r*C.r;
        double delta = f*f - 4.0*e*g;
        if (dcmp(delta) < 0) return 0;
        else if (dcmp(delta) == 0)
        {
            t1 = t2 = -f/(2.0*e);
            sol.push_back(L.point(t1));
            return 1;
        }
        t1 = (-f - sqrt(delta))/(2.0 * e); sol.push_back(L.point(t1));
        t2 = (-f + sqrt(delta))/(2.0 * e); sol.push_back(L.point(t2));
        return 2;
    }
    //判断并求出两圆的交点
    double angle(Vtor v) { return atan2(v.y, v.x); }
    int getCircleIntersection(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;
    }
    //求点到圆的切线
    int getTangents(Point p,Circle C,Vtor* v)
    {
        Vtor u = C.c - p;
        double dis = Length(u);
        if (dis < C.r)  return 0;
        else if (dcmp(dis - C.r) == 0)
        {
            v[0] = Rotate(u,PI/2.0);
            return 1;
        }
        else
        {
            double ang = asin(C.r / dis);
            v[0] = Rotate(u, -ang);
            v[1] = Rotate(u, +ang);
            return 2;
        }
    }
    //求两圆的切线
    int getCircleTangents(Circle A,Circle B,Point *a,Point *b)
    {
        int cnt = 0;
        if (A.r < B.r) { swap(A,B); swap(a, b) ; }
        //圆心距的平方
        double d2 = (A.c.x - B.c.x)*(A.c.x - B.c.x) + (A.c.y - B.c.y)*(A.c.y - B.c.y);
        double rdiff = A.r - B.r;
        double rsum = A.r + B.r;
        double base = angle(B.c - A.c);
        //重合有无限多条
        if (d2 == 0 && dcmp(A.r - B.r) == 0) return -1;
        //内切
        if (dcmp(d2 - rdiff*rdiff) == 0)
        {
            a[cnt] = A.point(base);
            b[cnt] = B.point(base); cnt++;
            return 1;
        }
        //有外公切线
        double ang = acos((A.r - B.r) / sqrt(d2));
        a[cnt] = A.point(base + ang); b[cnt] = B.point(base + ang); cnt++;
        a[cnt] = A.point(base - ang); b[cnt] = B.point(base - ang); cnt++;
    
        //一条内切线
        if (dcmp(d2 - rsum*rsum) == 0)
        {
            a[cnt] = A.point(base); b[cnt] = B.point(PI + base); cnt++;
        }//两条内切线
        else if (dcmp(d2 - rsum*rsum) > 0)
        {
            double ang = acos((A.r + B.r) / sqrt(d2));
            a[cnt] = A.point(base + ang); b[cnt] = B.point(base + ang); cnt++;
            a[cnt] = A.point(base - ang); b[cnt] = B.point(base - ang); cnt++;
        }
        return cnt;
    }
    
    
    //**********************************
    Circle CircumscribedCircle(Point A,Point B,Point C)
    {
        Point tmp1 = Point((B.x + C.x) / 2.0,(B.y + C.y) / 2.0);
        Vtor u = C - tmp1;
        u = Rotate(u,PI/2.0);
        Point tmp2 = Point((A.x + C.x) / 2.0,(A.y + C.y) / 2.0);
        Vtor v = C - tmp2;
        v = Rotate(v,-PI/2.0);
        Point c = GetLineIntersection(tmp1,u,tmp2,v);
        double r = Length(C - c);
        return Circle(c,r);
    }
    //得到法向量就得到了这个方向上的向量了
    //Circle work1(Point p1, Point p2, Point p3)
    // {
    //     Vtor nor1 = Normal(p1 - p2);
    //     Vtor nor2 = Normal(p2 - p3);
    //     Point mid1 = (p1 + p2) / 2.0;
    //     Point mid2 = (p2 + p3) / 2.0;
    //     Point O = GetLineIntersection(mid1, nor1, mid2, nor2);
    //     double r = Length(O - p1);
    //     return Circle(O, r);
    //}
    
    //不知道为什么我按常规的求法就是不对
    //Circle InscribedCircle(Point A,Point B,Point C)
    //{
    //    Vtor u = A - B;
    //    Vtor v = C - B;
    //    double ang = Angle(u,v);
    //    Vtor vv= Rotate(v,ang / 2.0);
    //    u = A - C;
    //    v = B - C;
    //    ang = Angle(u,v);
    //    Vtor uu = Rotate(u,ang / 2.0);
    //    Point c = GetLineIntersection(B,vv,C,uu);
    //    double r = DistanceToLine(c,A,C);
    //    return Circle(c,r);
    //}
    Circle work2(Point p1, Point p2, Point p3) {
        Vtor v11 = p2 - p1;
        Vtor v12 = p3 - p1;
        Vtor v21 = p1 - p2;
        Vtor v22 = p3 - p2;
        double ang1 = (angle(v11) + angle(v12)) / 2.0;
        double ang2 = (angle(v21) + angle(v22)) / 2.0;
        Vtor vec1 = Vtor(cos(ang1), sin(ang1));
        Vtor vec2 = Vtor(cos(ang2), sin(ang2));
        Point O = GetLineIntersection(p1, vec1, p2, vec2);
        double r = DistanceToLine(O, p1, p2);
        return Circle(O, r);
    }
    vector<Point> solve4(Point A,Point B,double r,Point C)
    {
        Vtor normal = Normal(B - A);
        normal = normal / Length(normal) * r;
        vector<Point> ans;
        double t1 = 0,t2 = 0;
        Vtor tA = A + normal,tB = B + normal;
        getLineCircleIntersection(Line(tA,tB,tB - tA),Circle(C, r),t1,t2,ans);
        tA = A - normal,tB = B - normal;
        getLineCircleIntersection(Line(tA,tB,tB - tA),Circle(C, r),t1,t2,ans);
        return ans;
    }
    vector<Point> solve5(Point A,Point B,Point C,Point D,double r)
    {
        Line lines[5];
        Vtor normal = Normal(B - A) * r;
        Point ta,tb,tc,td;
        ta = A + normal,tb = B + normal;
        lines[0] = Line(ta,tb,tb - ta);
        ta = A - normal,tb = B - normal;
        lines[1] = Line(ta,tb,tb - ta);
    
        normal = Normal(D - C) * r;
        tc = C + normal,td = D + normal;
        lines[2] = Line(tc,td,td - tc);
        tc = C - normal,td = D - normal;
        lines[3] = Line(tc,td,td - tc);
        vector<Point> ans;
        ans.push_back(GetLineIntersection(lines[0].p,lines[0].v,lines[2].p,lines[2].v));
        ans.push_back(GetLineIntersection(lines[0].p,lines[0].v,lines[3].p,lines[3].v));
        ans.push_back(GetLineIntersection(lines[1].p,lines[1].v,lines[2].p,lines[2].v));
        ans.push_back(GetLineIntersection(lines[1].p,lines[1].v,lines[3].p,lines[3].v));
        return ans;
    }
    vector<Point> solve6(Circle C1,Circle C2,double r)
    {
        vector<Point> vc;
        getCircleIntersection(Circle(C1.c, C1.r + r),Circle(C2.c, C2.r + r),vc);
        return vc;
    }
    
    string op;
    double x[10];
    
    int main()
    {
    //    Read();
    
        while (cin>>op)
        {
            if (op == "CircumscribedCircle")
            {
                for (int i = 0; i < 6; ++i) cin>>x[i];
                Circle ans = CircumscribedCircle(Point(x[0],x[1]),Point(x[2],x[3]),Point(x[4],x[5]));
    //            Circle ans = work1(Point(x[0],x[1]),Point(x[2],x[3]),Point(x[4],x[5]));
                printf("(%.6lf,%.6lf,%.6lf)
    ",ans.c.x,ans.c.y,ans.r);
            }
            else if (op == "InscribedCircle")
            {
                for (int i = 0; i < 6; ++i) cin>>x[i];
    //            Circle ans = InscribedCircle(Point(x[0],x[1]),Point(x[2],x[3]),Point(x[4],x[5]));
                Circle ans = work2(Point(x[0],x[1]),Point(x[2],x[3]),Point(x[4],x[5]));
                printf("(%.6lf,%.6lf,%.6lf)
    ",ans.c.x,ans.c.y,ans.r);
            }
            else if (op == "TangentLineThroughPoint")
            {
                for (int i = 0; i < 5; ++i) cin>>x[i];
                Vtor vc[5];
                int len = getTangents(Point(x[3],x[4]),Circle( Point(x[0],x[1]), x[2] ),vc);
                double tmp[5];
                for (int i = 0; i < len; ++i)
                {
                    double ang = angle(vc[i]);
                    if (ang < 0) ang += PI;
                    ang = fmod(ang,PI);
                    tmp[i] = ang*180/PI;
                }
                sort(tmp,tmp + len);
                printf("[");
                for (int i = 0; i < len; ++i)
                {
                    printf("%.6lf",tmp[i]);
                    if (i != len - 1) printf(",");
                }
                printf("]
    ");
            }
            else if (op == "CircleThroughAPointAndTangentToALineWithRadius")
            {
                for (int i = 0; i < 7; ++i) cin>>x[i];
                vector<Point> vc = solve4(Point(x[2],x[3]),Point(x[4],x[5]),x[6],Point(x[0],x[1]));
                sort(vc.begin(),vc.end());
                printf("[");
                for (size_t i = 0; i < vc.size(); ++i)
                {
                    printf("(%.6lf,%.6lf)",vc[i].x,vc[i].y);
                    if (i != vc.size() - 1) printf(",");
                }
                printf("]
    ");
            }
            else if (op == "CircleTangentToTwoLinesWithRadius")
            {
                for (int i = 0; i < 9; ++i) cin>>x[i];
                vector<Point> vc = solve5(Point(x[0],x[1]),Point(x[2],x[3]),Point(x[4],x[5]),Point(x[6],x[7]),x[8]);
                sort(vc.begin(),vc.end());
                printf("[");
                for (size_t i = 0; i < vc.size(); ++i)
                {
                    printf("(%.6lf,%.6lf)",vc[i].x,vc[i].y);
                    if (i != vc.size() - 1) printf(",");
                }
                printf("]
    ");
            }
            else
            {
                for (int i = 0; i < 7; ++i) cin>>x[i];
                vector<Point> vc = solve6(Circle(Point(x[0],x[1]),x[2]),Circle(Point(x[3],x[4]),x[5]),x[6]);
                sort(vc.begin(),vc.end());
                printf("[");
                for (size_t i = 0; i < vc.size(); ++i)
                {
                    printf("(%.6lf,%.6lf)",vc[i].x,vc[i].y);
                    if (i != vc.size() - 1) printf(",");
                }
                printf("]
    ");
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    hdu 2222 Keywords Search
    Meet and Greet
    hdu 4673
    hdu 4768
    hdu 4747 Mex
    uva 1513 Movie collection
    uva 12299 RMQ with Shifts
    uva 11732 strcmp() Anyone?
    uva 1401
    hdu 1251 统计难题
  • 原文地址:https://www.cnblogs.com/E-star/p/3223585.html
Copyright © 2011-2022 走看看