• 最小圆覆盖


    XXI.最小圆覆盖

    随机增量法。

    引理1.对于任意一组点集\(\mathbb{S}\)和某点\(P\),则\(P\)要么在\(\mathbb{S}\)的外接圆内,要么在\({\mathbb{S}\cup P}\)的外接圆上。

    于是我们可以设计出如下的解法:

    我们枚举一个\(1\sim n\)的变量i,并判断当前点是否在当前外接圆内。如果在的话,直接跳过;否则我们就找到了当前集合所对应的外接圆的端点之一。令此时的外接圆即为当前点本身。

    我们考虑再枚举一个\(1\sim i-1\)的变量j,并判断当前点是否在当前外接圆内。如果在的话,直接跳过;否则我们就找到了当前集合所对应的外接圆的另一个端点。令ij作为此时的外接圆的直径。

    我们考虑最后枚举一个\(1\sim j-1\)的变量k,重复上述操作。如果还不在的话,则我们已经知道了i,j,k三点,三点确定一个圆。于是我们就可以直接解出该圆。

    具体而言,我们作出三点间两对点的中垂线,然后求出两条中垂线的交点即可。中垂线可以简单由两点的中点和两点间向量旋转\(90^\circ\)得到。

    下面是复杂度分析。可以使用主定理证明,若我们random_shuffle一下点集,则其期望复杂度是\(O(n)\)的。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define double long double
    int n;
    struct Vector{
    	double x,y;
    	Vector(){}
    	Vector(double X,double Y){x=X,y=Y;}
    	friend Vector operator +(const Vector &u,const Vector &v){return Vector(u.x+v.x,u.y+v.y);}
    	friend Vector operator -(const Vector &u,const Vector &v){return Vector(u.x-v.x,u.y-v.y);}
    	friend Vector operator *(const Vector &u,const double &v){return Vector(u.x*v,u.y*v);}
    	friend Vector operator /(const Vector &u,const double &v){return Vector(u.x/v,u.y/v);}
    	friend double operator &(const Vector &u,const Vector &v){return u.x*v.y-u.y*v.x;}//cross times
    	friend double operator |(const Vector &u,const Vector &v){return u.x*v.x+u.y*v.y;}//point times
    	double operator ~()const{return sqrt(x*x+y*y);}//the modulo of a vector
    	double operator !()const{return atan2(y,x);}//the angle of a vector
    	void read(){scanf("%Lf%Lf",&x,&y);}
    	void print(){printf("(%Lf,%Lf)",x,y);}
    }p[100100];
    typedef Vector Point;
    struct Line{
    	Point x,y;
    	Vector z;
    	Line(){}
    	Line(Point X,Point Y){x=X,y=Y,z=Y-X;}
    	friend Point operator &(const Line &u,const Line &v){return u.x+u.z*((v.z&(u.x-v.x))/(u.z&v.z));}
    };
    typedef Line Segment;
    struct Circle{
    	Point o;
    	double r;
    	Circle(){}
    	Circle(Point O,double R=0){o=O,r=R;}
    	Circle(Point X,Point Y){o=(X+Y)/2,r=~(o-X);}
    	Circle(Point X,Point Y,Point Z){
    		Line u=Line((X+Y)/2,(X+Y)/2+Vector(Y.y-X.y,X.x-Y.x));
    		Line v=Line((Y+Z)/2,(Y+Z)/2+Vector(Z.y-Y.y,Y.x-Z.x));
    		o=u&v;
    		r=~(o-Y);
    	}
    	friend bool operator &(const Circle &u,const Point &v){return ~(u.o-v)<=u.r;}
    };
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)p[i].read();
    	random_shuffle(p+1,p+n+1);
    	Circle O=Circle(p[1]);
    	for(int i=2;i<=n;i++){
    		if(O&p[i])continue;
    		O=Circle(p[i]);
    		for(int j=1;j<i;j++){
    			if(O&p[j])continue;
    			O=Circle(p[i],p[j]);
    			for(int k=1;k<j;k++)if(!(O&p[k]))O=Circle(p[i],p[j],p[k]);
    		}
    	}
    	printf("%.10Lf\n%.10Lf %.10Lf\n",O.r,O.o.x,O.o.y);
    	return 0;
    }
    

  • 相关阅读:
    eclipse p2更新官网wiki的例子
    打包完的rcp产品svn不储存密码问题
    hudson 使用节点打包出现ClassNotFoundException: org.jvnet.hudson.maven3.agent.Maven3Main 错误
    maven 安装第三方jar到本地 出现 The goal you specified requires a project to execute but there is no POM in this directory 错误
    利用tycho插件自动生成pom文件
    蒙特卡洛(Monte Carlo)方法求面积
    笨办法学Python(learn python the hard way)--练习程序42
    笨办法学Python(learn python the hard way)--练习程序41
    笨办法学Python(learn python the hard way)--练习程序39-40
    笨办法学Python(learn python the hard way)--练习程序31-35
  • 原文地址:https://www.cnblogs.com/Troverld/p/14619394.html
Copyright © 2020-2023  润新知