【计算几何】【UVA 12304】2D Geometry 110 in 1!

来源:互联网 发布:网络作家富豪榜2015 编辑:程序博客网 时间:2024/05/17 22:48

套用计算几何模板。
EPS调成1e-6,再小判定圆和直线相切受影响。
这题怕卡读入,用c的输入输出,不是很习惯。并且c的输入输出好像和complex有些不兼容(real()imag()成员不能读入,在自己的机器上能通过编译但是评测机上不行),于是额外敲了get_point()函数。

#include<cstdio>#include<cstring>#include<complex>#include<vector>#include<algorithm>using namespace std;typedef complex<double> Coord;typedef Coord Point;typedef Coord Vec;const double EPS=1e-6,PI=acos(-1);int sgn(double x){    return fabs(x)<EPS?0:           x<0?-1:1;}struct PointCmp{    bool operator()(Point P,Point Q)    {        return sgn(P.real()-Q.real())?               P.real()<Q.real():               P.imag()<Q.imag();    }};Point get_point(){    double x,y;    scanf("%lf%lf",&x,&y);    return Point(x,y);}double Cross(Vec A,Vec B){    return imag(conj(A)*B);}Vec Normal(Vec A){    return Vec(-A.imag(), A.real())/abs(A);}struct Line{    Point p;    Vec v;    Line(Point p,Vec v):p(p),v(v) {}    Point point(double t)    {        return p+t*v;    }};double DistanceToLine(Point p,Line l){    return Cross(l.v,p-l.p)/abs(l.v);}Point GetLineIntersection(Line l1,Line l2){    return l1.point(Cross(l2.v,l1.p-l2.p)/Cross(l1.v,l2.v));}struct Circle{    Point c;    double r;    Circle() {}    Circle(Point c,double r):c(c),r(r) {}    Point point(double t)    {        return c+polar(r,t);    }};int getTangents(Point p,Circle C,vector<Point> &sol){    Vec u=p-C.c;    double d=abs(u);    if(d<C.r)return 0;    else if(sgn(d-C.r)==0)    {        sol.push_back(p);        return 1;    }    double base=arg(u),ang=acos(C.r/d);    sol.push_back(C.point(base+ang));    sol.push_back(C.point(base-ang));    return 2;}int getLineCircleIntersecion(Line L,Circle C,vector<Point> &sol){    double a=L.v.real(),b=L.p.real()-C.c.real(),           c=L.v.imag(),d=L.p.imag()-C.c.imag();    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(sgn(delta)<0)return 0;    if(sgn(delta)==0)    {        double t=-f/2/e;        sol.push_back(L.point(t));        return 1;    }    double 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 getCircleCircleIntersection(Circle C1, Circle C2,vector<Point>& sol){    double d=abs(C1.c - C2.c);    if(sgn(d)==0&&sgn(C1.r-C2.r)==0)return -1;    if(C1.r+C2.r<d||d<fabs(C1.r-C2.r))return 0;    double a=arg(C2.c - C1.c),           da=acos((d*d+C1.r*C1.r-C2.r*C2.r)/(2*d*C1.r));    if(sgn(da)==0)    {        sol.push_back(C1.point(a));        return 1;    }    sol.push_back(C1.point(a-da));    sol.push_back(C1.point(a+da));    return 2;}void CircumscribedCircle(){    Point p[3];    double tx,ty;    for(int i=0; i!=3; ++i)        p[i]=get_point();    Point p0=(p[1]+p[2])/2.0,          p2=(p[1]+p[0])/2.0;    Line l0(p0,Normal(p[2]-p[1])),         l2(p2,Normal(p[0]-p[1]));    Circle C;    C.c=GetLineIntersection(l0,l2);    C.r=abs(C.c-p[1]);    printf("(%.6lf,%.6lf,%.6lf)\n",C.c.real(),C.c.imag(),C.r);}void InscribedCircle(){    Point p[3];    for(int i=0; i!=3; ++i)        p[i]=get_point();    double arg0=(arg(p[1]-p[0])+arg(p[2]-p[0]))/2,           arg2=(arg(p[1]-p[2])+arg(p[0]-p[2]))/2;    Line l0(p[0],polar(1.0,arg0)),         l2(p[2],polar(1.0,arg2));    Circle C;    C.c=GetLineIntersection(l0,l2);    C.r=fabs(DistanceToLine(C.c,Line(p[0],p[2]-p[0])));    printf("(%.6lf,%.6lf,%.6lf)\n",C.c.real(),C.c.imag(),C.r);}void TangentLineThroughPoint(){    Circle C;    Point P;    C.c=get_point();    scanf("%lf",&C.r);    P=get_point();    vector<Point> ans;    getTangents(P,C,ans);    vector<double> sol;    for(int i=0; i!=ans.size(); ++i)    {        sol.push_back(arg(ans[i]-P)*180/PI);        if(sol.back()<0)sol.back()+=180;    }    sort(sol.begin(),sol.end());    printf("[");    for(int i=0; i!=sol.size(); ++i)    {        if(i)printf(",");        printf("%.6lf",sol[i]);    }    printf("]\n");}void CircleThroughAPointAndTangentToALineWithRadius(){    Circle C;    Point p[2];    C.c=get_point();    p[0]=get_point();    p[1]=get_point();    scanf("%lf",&C.r);    Vec mov=Normal(p[1]-p[0])*C.r;    Line L0(p[0]+mov,p[1]-p[0]),L1(p[0]-mov,p[1]-p[0]);    vector<Point> sol;    getLineCircleIntersecion(L0,C,sol);    getLineCircleIntersecion(L1,C,sol);    sort(sol.begin(),sol.end(),PointCmp());    printf("[");    for(int i=0; i!=sol.size(); ++i)    {        if(i)printf(",");        printf("(%.6lf,%.6lf)",sol[i].real(),sol[i].imag());    }    printf("]\n");}void CircleTangentToTwoLinesWithRadius(){    Point p[4];    double r;    for(int i=0; i!=4; ++i)        p[i]=get_point();    scanf("%lf",&r);    Vec mov=Normal(p[1]-p[0])*r;    Line L0(p[0]+mov,p[1]-p[0]),L1(p[0]-mov,p[1]-p[0]);    mov=Normal(p[3]-p[2])*r;    Line L2(p[2]+mov,p[3]-p[2]),L3(p[2]-mov,p[3]-p[2]);    vector<Point> sol;    sol.push_back(GetLineIntersection(L0,L2));    sol.push_back(GetLineIntersection(L0,L3));    sol.push_back(GetLineIntersection(L1,L2));    sol.push_back(GetLineIntersection(L1,L3));    sort(sol.begin(),sol.end(),PointCmp());    printf("[");    for(int i=0; i!=sol.size(); ++i)    {        if(i)printf(",");        printf("(%.6lf,%.6lf)",sol[i].real(),sol[i].imag());    }    printf("]\n");}void CircleTangentToTwoDisjointCirclesWithRadius(){    Circle C[2];    double r;    for(int i=0; i!=2; ++i)    {        C[i].c=get_point();        scanf("%lf",&C[i].r);    }    scanf("%lf",&r);    C[0].r+=r;    C[1].r+=r;    vector<Point> sol;    getCircleCircleIntersection(C[0],C[1],sol);    sort(sol.begin(),sol.end(),PointCmp());    printf("[");    for(int i=0; i!=sol.size(); ++i)    {        if(i)printf(",");        printf("(%.6lf,%.6lf)",sol[i].real(),sol[i].imag());    }    printf("]\n");}int main(){    for(char s[128]; scanf("%s",s)!=EOF;)    {        if(!strcmp(s,"CircumscribedCircle"))            CircumscribedCircle();        else if(!strcmp(s,"InscribedCircle"))            InscribedCircle();        else if(!strcmp(s,"TangentLineThroughPoint"))            TangentLineThroughPoint();        else if(!strcmp(s,"CircleThroughAPointAndTangentToALineWithRadius"))            CircleThroughAPointAndTangentToALineWithRadius();        else if(!strcmp(s,"CircleTangentToTwoLinesWithRadius"))            CircleTangentToTwoLinesWithRadius();        else if(!strcmp(s,"CircleTangentToTwoDisjointCirclesWithRadius"))            CircleTangentToTwoDisjointCirclesWithRadius();    }}
原创粉丝点击