首页 > 其他 > 详细

[AHOI2012]信号塔(最小圆覆盖)

时间:2020-03-10 23:33:45      阅读:78      评论:0      收藏:0      [点我收藏+]

[AHOI2012]信号塔(luogu)

Solution

一句话题意,坐标系中有 n 个点(坐标为实数),求一个半径最小的圆,使它包含所有的点

可以推出:一定有四个点(n>=4时),使其他所有点在这四个点围成的四边形内

于是要求的圆为这个四边形的外接圆,即圆为某三点的外接圆

于是可以枚举这三个点

从 1 < = i < = n 依次求出包含前 i 个点的半径最小圆

玄学复杂度 O(n)

Code

 

#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <cmath>
#define db double
using namespace std;
const int N=1e6+10;
struct point
{
    db x,y;
}d[N],O;
db R;
int n;
db dis(point a,point b)
{
    db xx=a.x-b.x,yy=a.y-b.y;
    return sqrt(xx*xx+yy*yy);
}
bool in(point pos)
{
    if(dis(pos,O)<=R) return true;
    return false;
}
void get_O(point i,point j,point k)
{
    db a,b,c,d,e,f;
    a=j.x-i.x,b=j.y-i.y;
    c=k.x-j.x,d=k.y-j.y;
    e=j.x*j.x+j.y*j.y-i.x*i.x-i.y*i.y;
    f=k.x*k.x+k.y*k.y-j.x*j.x-j.y*j.y;
    O.x=(f*b-e*d)/(c*b-a*d)/2; 
    O.y=(a*f-e*c)/(a*d-b*c)/2;
    R=dis(O,i); 
}
void get_O(point a,point b)
{
    O.x=(a.x+b.x)/2;
    O.y=(a.y+b.y)/2;
    R=dis(a,b)/2;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%lf%lf",&d[i].x,&d[i].y);
    O=d[1];
    for(int i=1;i<=n;i++)
    {
        if(in(d[i])) continue;
        O=d[i];
        for(int j=1;j<i;j++)
        {
            if(in(d[j])) continue;
            get_O(d[i],d[j]);
            for(int k=1;k<j;k++)
                if(!in(d[k])) get_O(d[i],d[j],d[k]);
        }
    }
    printf("%.2lf %.2lf %.2lf",O.x,O.y,R);
    return 0;
}

 

 

 

[AHOI2012]信号塔(最小圆覆盖)

原文:https://www.cnblogs.com/hsez-cyx/p/12459242.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!