最小圆覆盖(随机增量法)

原理:

设前k个点的最小覆盖圆为Ck

在前i-1个点的最小覆盖圆C(i-1)的基础上

Ⅰ 第i个点不被C(i-1)覆盖,则点i一定在Ci上,做固定了点i、前i个点的最小圆覆盖

  初始让Ci的圆心为点i,0为半径,然后逐步把前i-1个点加到Ci内

  枚举点j,j∈[1,i-1]

  1.点j不被Ci覆盖,则构建一个新的Cj,点i和点j一定在Cj上,做固定了点i j,前j个点的最小圆覆盖

    初始让Cj的圆心为i和j的中点,i和j距离的一半为半径,然后逐步把前j-1个点加到Cj内

    枚举点k,k∈[1,j-1]

      a. 点k不被Cj覆盖,则构建一个新的Ck,点i,j,k一定可以构成一个圆,此时的圆覆盖了i j 和 前k个点

      b. 点k被Cj覆盖,Cj不变

  2.点j被Ci覆盖,Ci不变

Ⅱ 第i个点被C(i-1)覆盖,Ci=C(i-1)

 

时间复杂度:

假设随机产生n个点,最小覆盖圆是C。因为三点共圆,当第n个点落在C的那3个点上时,说明C是重构的。

所以随机生成n个点,最后一个点不在前n-1个点的最小覆盖圆上的概率为3/n

总复杂度为线性的

 

要把原先点的顺序随机打乱

如果ijk三点幸运的共线了,可以取他们较远的两个点的中点为圆心

 

#include<cstdio> 
#include<cmath>
#include<algorithm>

using namespace std;

#define N 1000001

struct Point
{
    double x,y;
}e[N]; 

struct Circle
{
    Point c;
    double r;
}a;

double dis(Point a,Point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

Circle mid(Point a,Point b)
{
    Circle o;
    o.c.x=(a.x+b.x)/2;
    o.c.y=(a.y+b.y)/2;
    o.r=dis(a,b)/2;
    return o;
}

Circle work(Point A,Point B,Point C)
{
    double a=B.x-A.x;
    double b=C.x-A.x;
    double c=B.y-A.y;
    double d=C.y-A.y;
    double e=(B.x*B.x-A.x*A.x+B.y*B.y-A.y*A.y)/2;
    double f=(C.x*C.x-A.x*A.x+C.y*C.y-A.y*A.y)/2;
    Circle cc;
    double m=a*d-b*c;
    if(abs(m)<1e-4)
    {
        double dis1=dis(A,C);
        double dis2=dis(B,C);
        if(dis1>dis2) return mid(A,C);
        return mid(B,C);
    }
    cc.c.x=(e*d-c*f)/m;
    cc.c.y=(a*f-b*e)/m;
    cc.r=dis(cc.c,A);
    return cc;
}

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;++i) scanf("%lf%lf",&e[i].x,&e[i].y);
    random_shuffle(e+1,e+n+1);
    a.c=e[1];
    for(int i=2;i<=n;++i)
        if(dis(e[i],a.c)>a.r) 
        {
            a.c=e[i];
            a.r=0;
            for(int j=1;j<i;++j)
                if(dis(e[j],a.c)>a.r)
                {
                    a=mid(e[i],e[j]);
                    for(int k=1;k<j;++k)
                    {
                        if(dis(e[k],a.c)>a.r)
                            a=work(e[i],e[j],e[k]);
                    //    printf("i=%d j=%d k=%d : %.2lf %.2lf %.2lf \n",i,j,k,a.c.x,a.c.y,a.r);
                    } 
                }
        }
    printf("%.2lf %.2lf %.2lf",a.c.x,a.c.y,a.r);
}

 

posted @ 2021-03-11 15:33  TRTTG  阅读(456)  评论(0编辑  收藏  举报