• ●UVA 10674 Tangents


    题链:

    https://vjudge.net/problem/UVA-10674

    题解:

    计算几何,求两个圆的公切线。

    《算法竞赛入门经典——训练指南》P266,讲得很清楚的。

    大致是分为6种情况——内含,重合,内切,相交,外切,相离这六个情况去处理,

    找到共通点,便于代码编写。

    代码:

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const double eps=1e-8;
    const double Pi=acos(-1);
    int sign(double x){
    	if(fabs(x)<=eps) return 0;
    	return x<0?-1:1;
    }
    struct Point{
    	double x,y;
    	Point(double _x=0,double _y=0):x(_x),y(_y){}
    	void Read(){scanf("%lf%lf",&x,&y);}
    };
    struct Circle{
    	Point o; double r;
    	Point GP(double a){//Get_Point
    		return Point(o.x+r*cos(a),o.y+r*sin(a));
    	}
    }C1,C2;
    struct Intersect{
    	Point P[2];
    	bool operator <(const Intersect &rtm) const{
    		return sign(P[0].x-rtm.P[0].x)<0||(sign(P[0].x-rtm.P[0].x)==0&&sign(P[0].y-rtm.P[0].y)<0);
    	}
    }ANS[7];
    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 * (Point A,double p){return Vector(A.x*p,A.y*p);}
    double operator ^ (Vector A,Vector B){return A.x*B.y-A.y*B.x;}
    double operator * (Vector A,Vector B){return A.x*B.x+A.y*B.y;}
    double GPA(Vector A){//Get_Polar_Angle
    	return atan2(A.y,A.x);
    }
    double GL(Vector A){//Get_Length
    	return sqrt(A*A);
    }
    int GCCI(Circle A,Circle B){//Get_Circle_Circle_Intersection
    	int cnt=0,a=0,b=1;
    	if(A.r<B.r) swap(A,B),swap(a,b);
    	Vector u=B.o-A.o;
    	double d=GL(u),rdec=A.r-B.r,radd=A.r+B.r;
    	if(sign(d-rdec)<0) return 0;					//内含
    	if(sign(d)==0&&A.r==B.r) return -1;				//重合,无线多
    	double base=GPA(u);
    	if(sign(d-rdec)==0){							//内切
    		ANS[++cnt].P[a]=A.GP(base); ANS[cnt].P[b]=B.GP(base);
    		return cnt;
    	}
    	double da=acos((A.r-B.r)/d);					//2条外公切线
    	ANS[++cnt].P[a]=A.GP(base+da); ANS[cnt].P[b]=B.GP(base+da);
    	ANS[++cnt].P[a]=A.GP(base-da); ANS[cnt].P[b]=B.GP(base-da);
    	if(sign(d-radd)==0){							//1条内公切线
    		ANS[++cnt].P[a]=A.GP(base); ANS[cnt].P[b]=B.GP(base+Pi);
    	}
    	else if(sign(d-radd)>0){						//2条内公切线
    		da=acos((A.r+B.r)/d);
    		ANS[++cnt].P[a]=A.GP(base+da); ANS[cnt].P[b]=B.GP(base+da+Pi);
    		ANS[++cnt].P[a]=A.GP(base-da); ANS[cnt].P[b]=B.GP(base-da+Pi);
    	}
    	return cnt;
    }
    int main(){
    	int cnt;
    	while(1){
    		C1.o.Read(); scanf("%lf",&C1.r);
    		C2.o.Read(); scanf("%lf",&C2.r);
    		if(!C1.o.x&&!C1.o.y&&!C1.r&&!C2.o.x&&!C2.o.y&&!C2.r) break;
    		cnt=GCCI(C1,C2);
    		printf("%d
    ",cnt);
    		if(cnt<=0) continue;
    		sort(ANS+1,ANS+cnt+1);
    		for(int i=1;i<=cnt;i++){
    			printf("%.5lf %.5lf %.5lf %.5lf %.5lf
    ",ANS[i].P[0].x,ANS[i].P[0].y,ANS[i].P[1].x,ANS[i].P[1].y,GL(ANS[i].P[1]-ANS[i].P[0]));
    		}
    		
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    86. 分隔链表
    85. 最大矩形
    84. 柱状图中最大的矩形
    82. 删除排序链表中的重复元素 II
    80. 删除排序数组中的重复项 II
    77. 组合
    java-xml
    java-反射
    springboot解决跨域问题(CorsConfig )
    解决oracle锁表
  • 原文地址:https://www.cnblogs.com/zj75211/p/8227597.html
Copyright © 2020-2023  润新知