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

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

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

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值