P2533 最小圆覆盖

题意

简单说一下做法,并不知道怎么证明:

假设当前求出了([1,i-1])的最小覆盖圆,现在考虑([1,i])的最小覆盖圆:
如果(i)在当前圆中就不必改动。
不然(i)必定在圆上,我们令圆心为(i),半径为(0)
现在固定了一个点,我们枚举(jin[1,i-1]),如果(j)不在当前圆中,我们固定(j)
现在固定了两个点,我们枚举(kin[1,j-1]),如果(k)不在当前圆中,就固定(k),现在固定了三个点,可以求出圆。

复杂度:期望(O(n))很假的样子,但就是真的。

固定三个点求圆:从两条弦做中垂线求交点便是圆心。

code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
const double eps=1e-12;
const double Pi=acos(-1.0);
int n;
struct Point
{
    double x,y;
    inline double len(){return x*x+y*y;}
    Point operator+(const Point a)const{return (Point){x+a.x,y+a.y};}
    Point operator-(const Point a)const{return (Point){x-a.x,y-a.y};}
    Point operator*(const double k){return (Point){x*k,y*k};}
    Point operator/(const double k){return (Point){x/k,y/k};}
    double operator*(const Point a)const{return x*a.y-y*a.x;}
    double operator&(const Point a)const{return x*a.x+y*a.y;}
}p[maxn];
inline int dcmp(double x)
{
	if(fabs(x)<=eps)return 0;
	return x<0?-1:1;
}
struct Line{Point p,v;};
inline Point turn(Point a,double theta)
{
	return (Point){a.x*cos(theta)-a.y*sin(theta),a.x*sin(theta)+a.y*cos(theta)};
} 
inline Point get(Point a,Point b){return b-a;}
inline Point getpoint(Line a,Line b)
{
    Point p1=a.p,p2=b.p,v1=a.v,v2=b.v;
    Point u=get(p1,p2);
    Point res=p1+v1*((u*v2)/(v1*v2));
    return res;
}
inline Point find_circle(Point a,Point b,Point c)
{
	return getpoint((Line){(a+b)/2.0,turn(get(a,b),Pi/2.0)},(Line){(a+c)/2.0,turn(get(a,c),Pi/2.0)});
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
	random_shuffle(p+1,p+n+1);
	Point now=(Point){0,0};double nowr=0;
	for(int i=1;i<=n;i++)
	{
		if(dcmp(get(now,p[i]).len()-nowr)<=0)continue;
		now=p[i],nowr=0;
		for(int j=1;j<i;j++)
		{
			if(dcmp(get(now,p[j]).len()-nowr)<=0)continue;
			now=(p[i]+p[j])/2.0;nowr=get(now,p[j]).len();
			for(int k=1;k<j;k++)
			{
				if(dcmp(get(now,p[k]).len()-nowr)<=0)continue;
				now=find_circle(p[i],p[j],p[k]);nowr=get(now,p[k]).len();
			}
		}
	}
	printf("%.10lf
%.10lf %.10lf",sqrt(nowr),now.x,now.y);
	return 0;
}
原文地址:https://www.cnblogs.com/nofind/p/12212520.html