bzoj 1337 最小圆覆盖

Posted jklover

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}

以上是关于bzoj 1337 最小圆覆盖的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2823: [AHOI2012]信号塔&&1336: [Balkan2002]Alien最小圆覆盖&&1337: 最小圆覆盖

BZOJ1336[Balkan2002]Alien最小圆覆盖 随机增量法

模板最小圆覆盖——bzoj1336

[bzoj1336] [Balkan2002]Alien最小圆覆盖

bzoj2280[Poi2011]Plot 二分+倍增+二分+最小圆覆盖

[bzoj2517]矩形覆盖