码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 1337 最小圆覆盖

时间:2019-02-16 19:32:26      阅读:254      评论:0      收藏:0      [点我收藏+]

标签:include   std   info   inline   online   mat   amp   random   www   

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\n",r);
    return 0;
}

bzoj 1337 最小圆覆盖

标签:include   std   info   inline   online   mat   amp   random   www   

原文地址:https://www.cnblogs.com/jklover/p/10388841.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!