两圆交点模板 2018icpc沈阳L

链接 : https://codeforces.com/gym/101955/problem/L

本来是过了的…但看了大佬的代码之后开始怀疑自己是怎么卡过去的

大佬的代码:

#include <bits/stdc++.h>
using namespace std;
const double Pi=acos(-1);
const double eps=1e-12;
const int N=1e5+5;
struct Point {
	double x,y;
	Point(double x=0,double y=0):x(x),y(y) {};
};
Point operator +(Point A,Point B) {
	return Point(A.x+B.x,A.y+B.y);
}
Point operator -(Point A,Point B) {
	return Point(A.x-B.x,A.y-B.y);
}
Point operator *(Point A,double B) {
	return Point(A.x*B,A.y*B);
}
Point operator /(Point A,double B) {
	return Point(A.x/B,A.y/B);
}
int dcmp(double x) {
	if(fabs(x)<eps)return 0;
	return x<0?-1:1;
}
bool operator<(const Point&a,const Point&b) {
	return a.x<b.x||(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(Point A,Point B) {
	return A.x*B.x+A.y*B.y;
}
double Length(Point A) {
	return sqrt(Dot(A,A));
}
double Cross(Point A,Point B) {
	return A.x*B.y-A.y*B.x;
}
double Angle(Point A,Point B) {//利用点积 求出向量 A B 的夹角 cos值 
	return acos(Dot(A,B)/Length(A)/Length(B));
}
double Angle(Point A) {
	return atan2(A.y, A.x);
}
struct Circle {   //圆
	Point c;
	double r;
	Circle(Point c = Point(0, 0), double r = 0):c(c),r(r) {}
	Point point(double a) {
		return Point(c.x+cos(a)*r,c.y+sin(a)*r);
	}
};
double dis(Point A,Point B) {
	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}
int circle_circle(Circle C1,Circle C2,vector<Point>&sol) { //圆与圆的交点,核心思想就是利用余弦定理求出两交点与圆心连线的夹角,显然可以根据已知距离,和圆心坐标,求出交点坐标,不同去画图,高中几何知识
	double d=Length(C1.c-C2.c);
	if(dcmp(d)==0) {
		if(dcmp(C1.r-C2.r)==0)return -1;
		return 0;
	}
	if(dcmp(C1.r+C2.r-d)<0)return 0;
	if(dcmp(fabs(C1.r-C2.r)-d)>0)return 0;
	double a=Angle(C2.c-C1.c);
	double da=acos((C1.r*C1.r+d*d-C2.r*C2.r)/(2*d*C1.r));
	Point p1=C1.point(a-da),p2=C1.point(a+da);
	sol.push_back(p1);
	if(p1==p2)return 1;
	sol.push_back(p2);
	return 2;
}
//由此往上的全部,即为两圆交点模板
//解方程无法换算不同的精度,而该方法可以有不同的eps,且精度和速度都比解方程更优秀
int T,n;
double R;
Point p[N];
double r[N];
int check(Point A) {
	for(int i=1; i<=n; i++) {
		double h=dis(A,p[i]);
		if(h<r[i]+eps)return 0;
	}
	return 1;
}
int main() {
	cin>>T;
	int kase=0;
	while(T--) {
		cin>>n>>R;
		Circle C0;
		C0.c=Point(0,0);
		C0.r=R;
		vector<Point>v;
		for(int i=1; i<=n; i++) {
			double x,y,z;
			scanf("%lf%lf%lf",&x,&y,&z);
			p[i]=Point(x,y);
			r[i]=z;
			Circle C1;
			C1.c=Point(x,y);
			C1.r=z;
			circle_circle(C0,C1,v);
		}
		double ans=0;
		int f=0;
		for(int i=0; i<v.size(); i++) {
			double x=-v[i].x;
			double y=-v[i].y;
			if(check(Point(x,y))) {
				f=1;
				break;
			}
		}
		if(f or v.size()==0) {
			printf("Case #%d: %.10lf\n",++kase,R*2);
			continue;
		}
		int h=v.size();
		for(int i=0; i<h; i++) {
			for(int j=0; j<h; j++) {
				if(i==j)continue;
				double res=dis(v[i],v[j]);
				ans=max(ans,res);
			}
		}
		printf("Case #%d: %.15lf\n",++kase,ans);
	}
	return 0;
}

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本程序是两圆相交求交点,输入信息为两圆的圆心坐标和半径值。如有更好的算法,欢迎交流!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值