●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;
}

  

原文地址:https://www.cnblogs.com/zj75211/p/8227597.html