bzoj2823: [AHOI2012]信号塔

题解

  

随机增量法求最小覆盖圆
期望复杂度 O(n)

代码

//随机增量法求最小圆覆盖 
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#define maxn 1000010
#define eps 1e-8
using namespace std;
typedef double real;
int N;
real r;
struct point
{
    real x, y;
    point(real x, real y):x(x),y(y){}
    point(){};
}pt[maxn], _, o;
struct vec
{
    point pt; real x, y;
    vec(point pt, real x, real y):pt(pt),x(x),y(y){}
    vec(){}
};
point operator+(point pt, vec v){return point(pt.x+v.x,pt.y+v.y);}
vec operator-(point p1, point p2){return vec(p2,p1.x-p2.x,p1.y-p2.y);}
vec operator+(vec v1, vec v2){return vec(_,v1.x+v2.x,v1.y+v2.y);}
vec operator-(vec v1, vec v2){return vec(_,v1.x-v2.x,v1.y-v2.y);}
vec operator*(vec v, real t){return vec(v.pt,v.x*t,v.y*t);}
vec operator/(vec v, real t){return vec(v.pt,v.x/t,v.y/t);}
real operator*(vec v1, vec v2){return v1.x*v2.y-v2.x*v1.y;}
point inter(vec v1, vec v2)
{
    vec u=v1.pt-v2.pt; double t=v2*u/(v1*v2);
    return v1.pt+v1*t;
}
point cen(point p1, point p2){return point((p1.x+p2.x)/2,(p1.y+p2.y)/2);}
point cen(point p1, point p2, point p3)
{
    vec a=p2-p1, b=p3-p1;
    a=vec(cen(p1,p2),-a.y,a.x), b=vec(cen(p1,p3),-b.y,b.x);
    return inter(a,b);
}
double sqr(double x){return x*x;}
double dist(point p1, point p2){return sqrt(sqr(p2.x-p1.x)+sqr(p2.y-p1.y));}
void work()
{
    int i, j, k;
    random_shuffle(pt+1,pt+N+1);
    o=pt[1];
    for(i=2;i<=N;i++)
    {
        if(dist(o,pt[i])<r+eps)continue;
        o=cen(pt[1],pt[i]), r=dist(o,pt[i]);
        for(j=1;j<i;j++)
        {
            if(dist(o,pt[j])<r+eps)continue;
            o=cen(pt[i],pt[j]), r=dist(o,pt[i]);
            for(k=1;k<j;k++)
            {
                if(dist(o,pt[k])<r+eps)continue;
                o=cen(pt[i],pt[j],pt[k]), r=dist(o,pt[i]);
            }
        }
    }
}
int main()
{
    int i;
    scanf("%d",&N);
    for(i=1;i<=N;i++)scanf("%lf%lf",&pt[i].x,&pt[i].y);
    work();
    printf("%.2lf %.2lf %.2lf",o.x,o.y,r);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值