bzoj 1337 最小圆覆盖

bzoj 1337 最小圆覆盖

  • 补充一个求三角形外心的向量法.用了点积的几何意义,很实用.出处.

    向量法求外心

  • 使用随机增量法求.首先随机打乱顺序,然后三重循环,选择当前在圆外的点更新圆,分别按照 (1/2/3) 个点确定圆的方式更新即可.

  • 由于随机一个点不在前 (i) 个点的最小覆盖圆内的概率是 (frac 3 i) ,可以证明这样的时间复杂度是 (O(n)) 的,这种做法可以推广到常数维度上,时间复杂度仍为 (O(n)) .

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pii pair<int,int>
inline int read()
{
	int x=0;
	bool pos=1;
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar())
		if(ch=='-')
			pos=0;
	for(;isdigit(ch);ch=getchar())
		x=x*10+ch-'0';
	return pos?x:-x;
}
const double eps=1e-9;
const int MAXN=1e5+10;
int dcmp(double x)
{
	return fabs(x)<=eps?0:(x>0?1:-1);
}
struct v2{
	double x,y;
	v2(double x=0,double y=0):x(x),y(y) {}
	v2 operator + (const v2 &rhs) const
		{
			return v2(x+rhs.x,y+rhs.y);
		}
	v2 operator / (const double &rhs) const
		{
			return v2(x/rhs,y/rhs);
		}
	v2 operator - (const v2 &rhs) const
		{
			return v2(x-rhs.x,y-rhs.y);
		}
	double operator * (const v2 &rhs) const
		{
			return x*rhs.y-y*rhs.x;
		}
	double modulus()
		{
			return sqrt(x*x+y*y);
		}
};
double dist(v2 a,v2 b)
{
	return (a-b).modulus();
}
v2 CirCentre(v2 a,v2 b,v2 c)
{
	v2 centre;
	double a1=b.x-a.x;
	double b1=b.y-a.y;
	double c1=(a1*a1+b1*b1)/2.0;
	double a2=c.x-a.x;
	double b2=c.y-a.y;
	double c2=(a2*a2+b2*b2)/2.0;
	double d=a1*b2-a2*b1;
	centre.x=a.x+(c1*b2-c2*b1)/d;
	centre.y=a.y+(a1*c2-a2*c1)/d;
	return centre;
}
bool incircle(v2 p,v2 centre,double r)
{
	return dcmp(dist(p,centre)-r)<=0;
}
void MinCircleCover(v2 *p,int n,v2 &centre,double &r)
{
	srand(time(NULL));
	random_shuffle(p+1,p+1+n);
	centre=p[1];
	r=0;
	for(int i=2;i<=n;++i)
		{
			if(!incircle(p[i],centre,r))
				{
					centre=p[i];
					r=0;
					for(int j=1;j<i;++j)
						{
							if(!incircle(p[j],centre,r))
								{
									centre=(p[i]+p[j])/2.0;
									r=(p[i]-p[j]).modulus()/2.0;
									for(int k=1;k<j;++k)
										{
											if(!incircle(p[k],centre,r))
												{
													centre=CirCentre(p[i],p[j],p[k]);
													r=dist(centre,p[i]);
												}	
										}
								}
						}
				}
		}
}
int n;
v2 p[MAXN];
int main()
{
	n=read();
	for(int i=1;i<=n;++i)
		scanf("%lf%lf",&p[i].x,&p[i].y);
	v2 centre;
	double r;
	MinCircleCover(p,n,centre,r);
	printf("%.3lf
",r);
	return 0;
}
原文地址:https://www.cnblogs.com/jklover/p/10388841.html