学习笔记--最小圆覆盖

随机化各点后暴力枚举,发现三点定的圆不能包含当前点就更新。。复杂度期望O(n)(不会证。。)

模板题:bzoj1336

#include<bits/stdc++.h>
#define db double
using namespace std;
const int N=100010;
const db eps=1e-7;;
struct gg{
    db x,y;
}node[N],O;
db r;
int dcmp(db x)
{return x<-eps?-1:x>eps;}
db pf(db x)
{return x*x;}
db dis(gg x,gg y)
{return sqrt(pf(x.x-y.x)+pf(x.y-y.y));}
void get(db a1,db b1,db c1,db a2,db b2,db c2)
{
    db k;k=a2/a1;
    O.y=(c2-k*c1)/(b2-k*b1);
    O.x=(c1-b1*O.y)/a1;
}
int idx[N],n;
int main()
{
    srand(23336666);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)idx[i]=i;
    random_shuffle(idx+1,idx+n+1);
    for(int i=1;i<=n;i++)
        scanf("%lf%lf",&node[idx[i]].x,&node[idx[i]].y);
    O.x=(node[1].x+node[2].x)/2,O.y=(node[1].y+node[2].y)/2;
    r=dis(O,node[1]);
    for(int i=3;i<=n;i++)
    {
        if(dcmp(dis(O,node[i])-r)>0)
        {
            O=node[i],r=0;
            for(int j=1;j<i;j++)
            {
                if(dcmp(dis(O,node[j])-r)>0)
                {
                    O.x=(node[i].x+node[j].x)/2;
                    O.y=(node[i].y+node[j].y)/2;
                    r=dis(O,node[i]);
                    for(int k=1;k<j;k++)
                    {
                        if(dcmp(dis(O,node[k])-r)>0)
                        {
                            get(
                            2*(node[j].x-node[i].x),2*(node[j].y-node[i].y),pf(node[j].x)+pf(node[j].y)-pf(node[i].x)-pf(node[i].y),
                            2*(node[k].x-node[i].x),2*(node[k].y-node[i].y),pf(node[k].x)+pf(node[k].y)-pf(node[i].x)-pf(node[i].y)
                            );
                            r=dis(O,node[i]);
                        }
                    }
                }
            }
        }
    }
    printf("%.10lf\n",r);
    printf("%.10lf %.10lf",O.x,O.y);        
}

猜你喜欢

转载自blog.csdn.net/caoyang1123/article/details/82685885