UVA12304直线,圆,点的综合应用

来源:互联网 发布:网络理财平台排行榜 编辑:程序博客网 时间:2024/06/07 06:30

虽然这道题是个简单题,但对于我这样的弱渣还是研究了好久,而且自己根据大白书写的代码始终不对,无奈最后还是抄袭大神代码,

通过这个题得到下面几条心得,

1.做计算几何一定要注意精度问题,很难有绝对的相等,主要相对精度而言

2.做计算几何比较繁琐,一定要理清思路,代码思路一定要清晰

由于感觉大神的代码思路清晰,而且代码风格比较好,特贴出大神代码

,以及我自己按照大白书写的始终WA的代码,留着没事思考人生:

大神代码:

#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<cstring>#include<algorithm>#include<vector>#include<map>#include<set>#include<string>using namespace std;const double eps=1e-6;const double pi=acos(-1.0);int dcmp(double x){    if(fabs(x)<eps) return 0;    return x>eps?1:-1;}struct point{    double x,y;    point(){}    point(double x,double y):x(x),y(y){}    point operator + (const point &t) const    {        return point(x+t.x,y+t.y);    }    point operator - (const point &t) const    {        return point(x-t.x,y-t.y);    }    point operator * (const double &t) const    {        return point(x*t,y*t);    }    point operator / (const double &t) const    {        return point(x/t,y/t);    }    bool operator < (const point &t) const    {        return x+eps<t.x||(!dcmp(x-t.x)&&y<t.y);    }    double len()    {        return sqrt(x*x+y*y);    }    double len2()    {        return x*x+y*y;    }    point normal()    {        return point(-y,x)/len();    }    void in()    {        cin>>x>>y;    }    void out()    {        printf("(%.6f,%.6f)",x,y);    }};double dis(point a,point b){    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}point rotate(point a,double ct){    return point(a.x*cos(ct)-a.y*sin(ct),a.y*cos(ct)+a.x*sin(ct));}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 fix(double x){    if(x<-eps) x+=pi;    return x*180./pi;}double angle(point v){    return atan2(v.y,v.x);}double disPointToLine(point a,point l,point r){    return fabs(cross(a-l,r-l))/dis(l,r);}struct Line{    point a,v;    void in()    {        a.in();        v.in();        v=v-a;    }    Line(){}    Line(point a,point v):a(a),v(v){}};void lineLineIntersect(Line l,Line r,vector<point> &sol){    double t=cross((r.a-l.a),r.v)/cross(l.v,r.v);    sol.push_back(l.a+l.v*t);}struct Circle{    point o;    double r;    void in()    {        o.in();        cin>>r;    }    point getpoint(double ct)    {        return point(r*cos(ct),r*sin(ct))+o;    }    void out()    {        printf("(%.6f,%.6f,%.6f)\n",o.x,o.y,r);    }    Circle(point o,double r):o(o),r(r){}    Circle(){}};void cirLineIntersect(Circle C,Line L,vector <point> &sol){    double e=L.v.len2(),f=dot(L.a-C.o,L.v)*2,g=(L.a-C.o).len2()-C.r*C.r;    double dlt=f*f-4*e*g;    if(dlt<-eps) return;    if(dlt<eps)    {        double t=-f/(2*e);        sol.push_back(L.v*t+L.a);        return ;    }    dlt=sqrt(dlt);    double t1=(-f+dlt)/(2*e),t2=(-f-dlt)/(2*e);    sol.push_back(L.v*t1+L.a);    sol.push_back(L.v*t2+L.a);}void cirCirIntersect(Circle C1,Circle C2, vector <point> &sol){    point v=C2.o-C1.o;    double d=v.len();    if(dcmp(d-C1.r-C2.r)>0) return;    double ct=angle(v),alf=acos((C1.r*C1.r+d*d-C2.r*C2.r)/(2*C1.r*d));    sol.push_back(C1.getpoint(ct+alf));    if(dcmp(alf)>eps) sol.push_back(C1.getpoint(ct-alf));}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 ox = (cy*(bx*bx+by*by) - by*(cx*cx+cy*cy))/d + p1.x;double oy = (bx*(cx*cx+cy*cy) - cx*(bx*bx+by*by))/d + p1.y;point o = point(ox, oy);return Circle(o,dis(o,p1));}Circle InscribedCircle(point p1, point p2, point p3){double a = dis(p2, p3);double b = dis(p1, p3);double c = dis(p1, p2);point o = (p1*a+p2*b+p3*c)/(a+b+c);return Circle(o, disPointToLine(o, p1, p2));}vector<double> TangentLineThroughPoint(point p,Circle c){    vector<double> sol;    point u=c.o-p;    double d=u.len();    if(d+eps<c.r) return sol;    else if(!dcmp(d-c.r))    {        sol.push_back(fix(angle(rotate(u,-pi/2))));    }    else    {        double alf=asin(c.r/d);        sol.push_back(fix(angle(rotate(u,-alf))));        sol.push_back(fix(angle(rotate(u,alf))));    }    sort(sol.begin(),sol.end());    return sol;}vector <point> CircleThroughAPointAndTangentToALineWithRadius(point o, Line L, double r) {vector <point> sol;point v = L.v.normal();cirLineIntersect(Circle(o, r), Line(L.a+v*r, L.v), sol);cirLineIntersect(Circle(o, r), Line(L.a-v*r, L.v), sol);sort(sol.begin(), sol.end());return sol;}vector <point> CircleTangentToTwoLinesWithRadius(Line L1, Line L2, double r) {vector <point> sol;point v1 = L1.v.normal();point v2 = L2.v.normal();lineLineIntersect(Line(L1.a+v1*r, L1.v), Line(L2.a+v2*r, L2.v), sol);lineLineIntersect(Line(L1.a+v1*r, L1.v), Line(L2.a-v2*r, L2.v), sol);lineLineIntersect(Line(L1.a-v1*r, L1.v), Line(L2.a+v2*r, L2.v), sol);lineLineIntersect(Line(L1.a-v1*r, L1.v), Line(L2.a-v2*r, L2.v), sol);sort(sol.begin(), sol.end());return sol;}vector <point> CircleTangentToTwoDisjointCirclesWithRadius(Circle C1, Circle C2, double r) {vector <point> sol;cirCirIntersect(Circle(C1.o, C1.r+r), Circle(C2.o, C2.r+r), sol);sort(sol.begin(), sol.end());return sol;}string op;void print(vector <point> sol) {printf("[");for(int i = 0; i < sol.size(); i++) {sol[i].out();if(i != sol.size()-1) printf(",");}printf("]\n");}int main() {while(cin >> op) {if(op == "CircumscribedCircle") {point a, b, c;a.in(), b.in(), c.in();CircumscribedCircle(a, b, c).out();}else if(op == "InscribedCircle") {point a, b, c;a.in(), b.in(), c.in();InscribedCircle(a, b, c).out();}else if(op == "TangentLineThroughPoint") {Circle c; point p;c.in(); p.in();vector <double> ans = TangentLineThroughPoint(p, c);printf("[");for(int i = 0; i < ans.size(); i++) {printf("%.6f", ans[i]);if(i != ans.size()-1) printf(",");}printf("]\n");}else if(op == "CircleThroughAPointAndTangentToALineWithRadius") {point p; Line l; double r;p.in(), l.in(), scanf("%lf", &r);print(CircleThroughAPointAndTangentToALineWithRadius(p, l, r));}else if(op == "CircleTangentToTwoLinesWithRadius") {Line L1, L2; double r;L1.in(); L2.in(); scanf("%lf", &r);print(CircleTangentToTwoLinesWithRadius(L1, L2, r));}else if(op == "CircleTangentToTwoDisjointCirclesWithRadius") {Circle c1, c2; double r;c1.in(); c2.in(); scanf("%lf", &r);print(CircleTangentToTwoDisjointCirclesWithRadius(c1, c2, r));}}return 0;}
自己的WA代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cstdlib>#include<cmath>#include<cctype>#include<string>#include<map>#include<vector>#include<set>using namespace std;const double eps=1e-6;const double  PI=acos(-1.0);int dcmp(double x){    if(fabs(x)<eps)        return 0;    return x>eps?1:-1;}struct Point{    double x,y;    Point(){}    Point(double x,double y):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 Point &a,const Point &b){    return a.x+eps<b.x||(!dcmp(a.x-b.x)&&a.y<b.y);}//bool operator ==(const Point &a,const Point &b)//{ //   return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;//}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;}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);}double DistaceToLine(Point P,Point A,Point B){    Vector v1=B-A,v2=P-A;    return fabs(Cross(v1,v2)/Length(v1));}double angle(Vector v){    return atan2(v.y,v.x);}double fix(double x){    if(x<-eps)        x+=PI;    return x*180.0/PI;}struct Line{    Point p;    Vector v;    Line() {}    Line(Point p,Vector v):p(p),v(v){};    Point point(double t)    {        return Point(v*t+p);    }};Point GetLineIntersection(Point P,Vector v,Point Q,Vector w){    Vector u=P-Q;    double t=Cross(w,u)/Cross(v,w);    return Vector(P+v*t);}struct Circle{    Point c;    double r;    Circle(Point c,double r):c(c),r(r){}    Circle() {}    Point point(double a)    {        return Point(c.x+cos(a)*r,c.y+sin(a)*r);    }};void getLineCircleIntersection(Line L,Circle C,vector<Point> &sol){    double t1,t2;    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(delta<-eps) return;    if(delta<eps)    {        t1=t2=-f/(2*e);        sol.push_back(L.point(t1));        return;    }        t1=(-f-sqrt(delta))/(2*e);        sol.push_back(L.point(t1));        t2=(-f+sqrt(delta))/(2*e);        sol.push_back(L.point(t2));}void getCircleIntersection(Circle C1,Circle C2,vector<Point> &sol){    double d=Length(C1.c-C2.c);    if(dcmp(d-C1.r-C2.r)>0) return;        double a=angle(C2.c-C1.c);        double da=acos((C1.r*C1.r+d*d-C2.r*C2.r)/(2*C1.r*d));        sol.push_back(C1.point(a+da));        if(dcmp(da)>eps)            sol.push_back(C1.point(a-da));}void work1(){   Point A,B,C;    cin>>A.x>>A.y>>B.x>>B.y>>C.x>>C.y;    Vector p1=A-B;    Vector t1=Normal(p1);    Point mid1=(A+B)/2;    Vector p2=C-B;    Vector t2=Normal(p2);    Point mid2=(B+C)/2;    Point T=GetLineIntersection(mid1,t1,mid2,t2);    double r=Length(A-T);    printf("(%.6f,%.6f,%.6f)\n",T.x,T.y,r); /*   Point p1,p2,p3;    cin>>p1.x>>p1.y>>p2.x>>p2.y>>p3.x>>p3.y;    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);    printf("(%.6f,%.6f,%.6f)\n",p.x,p.y,Length(p1-p));    */}void work2(){    Point A,B,C;    cin>>A.x>>A.y>>B.x>>B.y>>C.x>>C.y;    Vector p1=A-B;    Vector p2=C-B;    Vector p3=C-A;    double radb=Angle(p1,p2);    double radc=Angle(p2,p3);    cout<<radb<<radc<<endl;    Vector BD=Rotate(p2,radb/2);    Vector CD=Rotate(p3,radc/2);    Point T=GetLineIntersection(B,BD,C,CD);    double r=DistaceToLine(T,A,B);    printf("(%.6f,%.6f,%.6f)\n",T.x,T.y,r);  /*  Point p1,p2,p3;    cin>>p1.x>>p1.y>>p2.x>>p2.y>>p3.x>>p3.y;    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);    double r=DistaceToLine(p,p1,p2);    printf("(%.6f,%.6f,%.6f)\n",p.x,p.y,r);*/}void work3(){    Circle C;    Point p;    cin>>C.c.x>>C.c.y>>C.r>>p.x>>p.y;   // Circle C(c,r);    Vector u=C.c-p;  //  cout<<u.x<<endl<<u.y<<endl;    double dist=Length(u);  //  cout<<dist<<endl;    if(dist+eps<C.r)        printf("[]\n");    else if(dcmp(dist-C.r)==0)    {        Vector v=Rotate(u,-PI/2);     //   cout<<v.x<<endl<<v.y<<endl;      //  double radd=rad+PI/2;       // if(radd==PI) radd-=PI;        printf("[%.6f]\n",fix(angle(v)));    }    else    {        double ang=asin(C.r/dist);        Vector v1=Rotate(u,-ang);        Vector v2=Rotate(u,ang);        double rad1=angle(v1);        double rad2=angle(v2);        if(rad1<rad2) swap(rad1,rad2);        printf("[%.6f,%.6f]\n",fix(rad1),fix(rad2));    }}void work4(){    Point p,p1,p2;    double r;    cin>>p.x>>p.y>>p1.x>>p1.y>>p2.x>>p2.y;    cin>>r;    Line L(p1,p2-p1);    Circle C(p,r);    vector <Point> sol;    Vector cc=Normal(L.v);    getLineCircleIntersection(Line(L.p+cc*r,L.v),C,sol);    getLineCircleIntersection(Line(L.p-cc*r,L.v),C,sol);    sort(sol.begin(),sol.end());   // cout<<sol.size()<<endl;    cout<<"[";    for(int i=0;i<sol.size();i++)    {        printf("(%.6f,%.6f)",sol[i].x,sol[i].y);        if(i!=sol.size()-1) cout<<",";    }    cout<<"]"<<endl;}void work5(){    Point p1,p2,p3,p4;    double r;    cin>>p1.x>>p1.y>>p2.x>>p2.y>>p3.x>>p3.y>>p4.x>>p4.y>>r;    Line L1(p1,p2-p1),L2(p3,p4-p3);    Vector LN1=Normal(L1.v);    Vector LN2=Normal(L2.v);    vector <Point> sol;    sol.push_back(GetLineIntersection(L1.p+LN1*r,L1.v,L2.p+LN2*r,L2.v));    sol.push_back(GetLineIntersection(L1.p+LN1*r,L1.v,L2.p-LN2*r,L2.v));    sol.push_back(GetLineIntersection(L1.p-LN1*r,L1.v,L2.p+LN2*r,L2.v));    sol.push_back(GetLineIntersection(L1.p-LN1*r,L1.v,L2.p-LN2*r,L2.v));    sort(sol.begin(),sol.end());    cout<<"[";    for(int i=0;i<sol.size();i++)    {        printf("(%.6f,%.6f)",sol[i].x,sol[i].y);        if(i!=sol.size()-1) cout<<",";    }    cout<<"]"<<endl;}void work6(){    Circle C1,C2;    double r;    cin>>C1.c.x>>C1.c.y>>C1.r>>C2.c.x>>C2.c.y>>C2.r>>r;    vector<Point> sol;     getCircleIntersection(Circle(C1.c,C1.r+r),Circle(C2.c,C2.r+r),sol);     sort(sol.begin(),sol.end());    cout<<"[";    for(int i=0;i<sol.size();i++)    {        printf("(%.6f,%.6f)",sol[i].x,sol[i].y);        if(i!=sol.size()-1) cout<<",";    }    cout<<"]"<<endl;}int main(){    string s;    while(cin>>s)    {        if(s=="CircumscribedCircle")            work1();        else if(s=="InscribedCircle")            work2();        else if(s=="TangentLineThroughPoint")            work3();        else if(s=="CircleThroughAPointAndTangentToALineWithRadius")            work4();        else if(s=="CircleTangentToTwoLinesWithRadius")            work5();        else if(s=="CircleTangentToTwoDisjointCirclesWithRadius")            work6();    }    return 0;}



0 0
原创粉丝点击