zoukankan      html  css  js  c++  java
  • UVA12304 2D Geometry 110 in 1!

    题意

    PDF

    分析

    三角形的外接圆

    维基百科上给出了计算公式,可以解方程推。

    三角形的内切圆

    维基百科上也给出了现成的公式,照样是可以推的。

    后三个操作

    都可以转化为直线、圆之间的交点问题。

    时间复杂度(O(T))

    精度问题

    对于第四个操作,如果不改现有的代码,精度必须调整至(10^{-6})

    要改的话可以特判直线与圆相切,求出对精确度要求很高的那个点。

    代码

    这大概是我写过的除数据结构题之外最长的代码了。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<algorithm>
    #include<bitset>
    #include<cassert>
    #include<ctime>
    #include<cstring>
    #define rg register
    #define il inline
    #define co const
    template<class T>il T read()
    {
        rg T data=0;
        rg int w=1;
        rg char ch=getchar();
        while(!isdigit(ch))
        {
            if(ch=='-')
                w=-1;
            ch=getchar();
        }
        while(isdigit(ch))
        {
            data=data*10+ch-'0';
            ch=getchar();
        }
        return data*w;
    }
    template<class T>T read(T&x)
    {
        return x=read<T>();
    }
    using namespace std;
    typedef long long ll;
    
    co double eps=1e-6;
    int dcmp(double x)
    {
        if(fabs(x)<eps)
            return 0;
        else
            return x<0?-1:1;
    }
    
    struct Point
    {
        double x,y;
        
        Point(double x=0,double y=0)
        :x(x),y(y){}
        
        bool operator<(co Point&rhs)co // edit 1
        {
            return dcmp(x-rhs.x)?x<rhs.x:y<rhs.y;
        }
        
        bool operator==(co Point&rhs)co
        {
            return dcmp(x-rhs.x)==0&&dcmp(y-rhs.y)==0;
        }
        
        double angle()
        {
            return atan2(y,x);
        }
    };
    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*(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);
    }
    
    double Dot(Vector A,Vector 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 Cross(Vector A,Vector B)
    {
        return A.x*B.y-A.y*B.x;
    }
    
    double Area2(Point A,Point B,Point C)
    {
        return Cross(B-A,C-A);
    }
    
    Vector Rotate(Vector A,double rad)
    {
        return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
    }
    
    Vector Normal(Vector A)
    {
        double L=Length(A);
        return Vector(-A.y/L,A.x/L);
    }
    
    Point LineLineIntersection(Point P,Vector v,Point Q,Vector w)
    {
        Vector u=P-Q;
        double t=Cross(w,u)/Cross(v,w);
        return P+v*t;
    }
    
    double DistanceToLine(Point P,Point A,Point B)
    {
        Vector v1=B-A,v2=P-A;
        return fabs(Cross(v1,v2))/Length(v1);
    }
    
    double DistanceToSegment(Point P,Point A,Point B)
    {
        if(A==B)
            return Length(P-A);
        Vector v1=B-A,v2=P-A,v3=P-B;
        if(dcmp(Dot(v1,v2))<0)
            return Length(v2);
        if(dcmp(Dot(v1,v3))>0)
            return Length(v3);
        return DistanceToLine(P,A,B);
    }
    
    Point PointLineProjection(Point P,Point A,Point B)
    {
        Vector 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 PolygonArea(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;
        Vector v;
        
        Line(Point p=0,Vector v=0)
        :p(p),v(v){}
        
        Line(double x1,double y1,double x2,double y2)
        {
        	Point p1(x1,y1);
        	Point p2(x2,y2);
        	p=p1;
        	v=p2-p1;
    	}
        
        Point point(double t)
        {
            return p+v*t;
        }
        
        Line move(double d)
        {
        	return Line(p+Normal(v)*d,v);
    	}
    };
    
    struct Circle
    {
        Point c;
        double r;
        
        Circle(Point c=0,double r=0)
        :c(c),r(r){}
        
        Point point(double a)
        {
            return Point(c.x+cos(a)*r,c.y+sin(a)*r);
        }
    };
    
    int LineCircleIntersection(Line L,Circle C,double&t1,double&t2,vector<Point>&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*e*g;
        if(dcmp(delta)<0)
            return 0;
        if(dcmp(delta)==0)
        {
            t1=t2=-f/(2*e);
            sol.push_back(L.point(t1));
            return 1;
        }
        t1=(-f-sqrt(delta))/(2*e);
        t2=(-f+sqrt(delta))/(2*e);
        sol.push_back(L.point(t1));
        sol.push_back(L.point(t2));
        return 2;
    }
    
    int CircleCircleIntersection(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=(C2.c-C1.c).angle();
        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;
    }
    
    co double PI=acos(-1);
    
    int PointCircleTangent(Point p,Circle C,vector<Vector>&sol)
    {
        Vector u=C.c-p;
        double dist=Length(u);
        if(dcmp(dist-C.r)<0)
            return 0;
        if(dcmp(dist-C.r)==0)
        {
            sol.push_back(Rotate(u,PI/2));
            return 1;
        }
        double ang=asin(C.r/dist);
        sol.push_back(Rotate(u,-ang));
        sol.push_back(Rotate(u,ang));
        return 2;
    }
    
    int CircleCircleTangent(Circle A,Circle B,vector<pair<Point,Point> >&sol)
    {
        int cnt=0;
        if(dcmp(A.r-B.r)<0) // notice the result here
            swap(A,B);
        double d=Length(A.c-B.c);
        double rdiff=A.r-B.r;
        double rsum=A.r+B.r;
        if(dcmp(d-rdiff)<0)
            return 0;
        
        double base=(B.c-A.c).angle();
        if(dcmp(d)==0&&dcmp(A.r-B.r)==0)
            return -1;
        if(dcmp(d-rdiff)==0)
        {
            sol.push_back(make_pair(A.point(base),B.point(base)));
            ++cnt;
            return 1;
        }
        
        double ang=acos((A.r-B.r)/d);
        sol.push_back(make_pair(A.point(base+ang),B.point(base+ang)));
        ++cnt;
        sol.push_back(make_pair(A.point(base-ang),B.point(base-ang)));
        ++cnt;
        if(dcmp(d-rsum)==0)
        {
            sol.push_back(make_pair(A.point(base),B.point(base+PI)));
            ++cnt;
        }
        else if(dcmp(d-rsum)>0)
        {
            double ang=acos((A.r+B.r)/d);
            sol.push_back(make_pair(A.point(base+ang),B.point(base+ang+PI)));
            ++cnt;
            sol.push_back(make_pair(A.point(base-ang),B.point(base-ang+PI)));
            ++cnt;
        }
        return cnt;
    }
    
    // Problem 1
    Circle CircumscribedCircle(Point p1,Point p2,Point p3)
    {
    	double Bx=p2.x-p1.x,By=p2.y-p1.y;
    	double Cx=p3.x-p1.x,Cy=p3.y-p1.y;
    	double D=2*(Bx*Cy-By*Cx);
    	double cx=(Cy*(Bx*Bx+By*By)-By*(Cx*Cx+Cy*Cy))/D+p1.x;
    	double cy=(Bx*(Cx*Cx+Cy*Cy)-Cx*(Bx*Bx+By*By))/D+p1.y;
    	Point p=Point(cx,cy);
    	return Circle(p,Length(p1-p));
    }
    
    // Problem 2
    Circle InscribedCircle(Point p1,Point p2,Point p3)
    {
    	double a=Length(p2-p3);
    	double b=Length(p3-p1);
    	double c=Length(p1-p2);
    	Point p=(p1*a+p2*b+p3*c)/(a+b+c);
    	return Circle(p,DistanceToLine(p,p1,p2));
    }
    
    // Problem 3
    // PointCircleTangent()
    
    // Problem 4
    vector<Point> CircleThroughPointTangentToLine(Point p,Line L,double r)
    { // require precision to be adjusted to 1e-6 here
    	vector<Point>ans;
    	double t1,t2;
    	LineCircleIntersection(L.move(-r),Circle(p,r),t1,t2,ans);
    	LineCircleIntersection(L.move(r),Circle(p,r),t1,t2,ans);
    	return ans;
    }
    
    // Problem 5
    vector<Point> CircleTangentToLine(Line a,Line b,double r)
    {
    	vector<Point>ans;
    	Line L1=a.move(-r),L2=a.move(r);
    	Line L3=b.move(-r),L4=b.move(r);
    	ans.push_back(LineLineIntersection(L1.p,L1.v,L3.p,L3.v));
    	ans.push_back(LineLineIntersection(L1.p,L1.v,L4.p,L4.v));
    	ans.push_back(LineLineIntersection(L2.p,L2.v,L3.p,L3.v));
    	ans.push_back(LineLineIntersection(L2.p,L2.v,L4.p,L4.v));
    	return ans;
    }
    
    // Problem 6
    vector<Point> CircleTangentToCircle(Circle c1,Circle c2,double r)
    {
    	vector<Point>ans;
    	Vector v=c2.c-c1.c;
    	double dist=Length(v);
    	if(dcmp(dist-c1.r-c2.r-r*2)>0)
    		return ans;
    	CircleCircleIntersection(Circle(c1.c,c1.r+r),Circle(c2.c,c2.r+r),ans);
    	return ans;
    }
    
    // Format
    double LineAngleDegree(Vector v)
    {
    	double ang=v.angle()*180/PI;
    	while(dcmp(ang)<0)
    		ang+=360;
    	while(dcmp(ang-180)>=0)
    		ang-=180;
    	return ang;
    }
    
    void format(Circle c)
    {
    	printf("(%lf,%lf,%lf)
    ",c.c.x,c.c.y,c.r);
    }
    
    void format(vector<double> ans)
    {
    	int n=ans.size();
    	sort(ans.begin(),ans.end());
    	printf("[");
    	if(n)
    	{
    		printf("%lf",ans[0]);
    		for(int i=1;i<n;++i)
    			printf(",%lf",ans[i]);
    	}
    	printf("]
    ");
    }
    
    void format(vector<Point> ans)
    {
    	int n=ans.size();
    	sort(ans.begin(),ans.end());
    	printf("[");
    	if(n)
    	{
    		printf("(%lf,%lf)",ans[0].x,ans[0].y);
    		for(int i=1;i<n;++i)
    			printf(",(%lf,%lf)",ans[i].x,ans[i].y);
    	}
    	printf("]
    ");
    }
    
    int main()
    {
    //  freopen(".in","r",stdin);
    //  freopen(".out","w",stdout);
    	string cmd;
    	double x1,y1,x2,y2,x3,y3,x4,y4,xp,yp,xc,yc,r1,r2,r;
    	while(cin>>cmd)
    	{
    		if(cmd=="CircumscribedCircle")
    		{
    			cin>>x1>>y1>>x2>>y2>>x3>>y3;
    			format(CircumscribedCircle(Point(x1,y1),Point(x2,y2),Point(x3,y3)));
    		}
    		else if(cmd=="InscribedCircle")
    		{
    			cin>>x1>>y1>>x2>>y2>>x3>>y3;
    			format(InscribedCircle(Point(x1,y1),Point(x2,y2),Point(x3,y3)));
    		}
    		else if(cmd=="TangentLineThroughPoint")
    		{
    			cin>>xc>>yc>>r>>xp>>yp;
    			vector<Vector>sol;
    			vector<double>ans;
    			int cnt=PointCircleTangent(Point(xp,yp),Circle(Point(xc,yc),r),sol);
    			for(int i=0;i<cnt;++i)
    				ans.push_back(LineAngleDegree(sol[i]));
    			format(ans);
    		}
    // CircleThroughAPointAndTangentToALineWithRadius 75 190 75 190 185 65 100
    		else if(cmd=="CircleThroughAPointAndTangentToALineWithRadius")
    		{
    			cin>>xp>>yp>>x1>>y1>>x2>>y2>>r;
    			format(CircleThroughPointTangentToLine(Point(xp,yp),Line(x1,y1,x2,y2),r));
    		}
    		else if(cmd=="CircleTangentToTwoLinesWithRadius")
    		{
    			cin>>x1>>y1>>x2>>y2>>x3>>y3>>x4>>y4>>r;
    			format(CircleTangentToLine(Line(x1,y1,x2,y2),Line(x3,y3,x4,y4),r));
    		}
    		else if(cmd=="CircleTangentToTwoDisjointCirclesWithRadius")
    		{
    			cin>>x1>>y1>>r1>>x2>>y2>>r2>>r;
    			format(CircleTangentToCircle(Circle(Point(x1,y1),r1),Circle(Point(x2,y2),r2),r));
    		}
    	}
        return 0;
    }
    
  • 相关阅读:
    discuz $_G变量
    php & 引用
    discuz模板引擎
    nginx正则表达式
    linux系统安装 dig和nslookup命令
    linux中的各种$号 位置参数变量
    memcache图形管理工具
    mysql 注入问题
    pycharm 连接mysql失败
    Bootstrap 常用网站
  • 原文地址:https://www.cnblogs.com/autoint/p/10142833.html
Copyright © 2011-2022 走看看