P2533 最小圆覆盖

题意

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

假设当前求出了\([1,i-1]\)的最小覆盖圆,现在考虑\([1,i]\)的最小覆盖圆:
如果\(i\)在当前圆中就不必改动。
不然\(i\)必定在圆上,我们令圆心为\(i\),半径为\(0\)
现在固定了一个点,我们枚举\(j\in[1,i-1]\),如果\(j\)不在当前圆中,我们固定\(j\)
现在固定了两个点,我们枚举\(k\in[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\n%.10lf %.10lf",sqrt(nowr),now.x,now.y);
	return 0;
}
posted @ 2020-01-19 09:56  nofind  阅读(103)  评论(0编辑  收藏  举报