问题 D: 【计算几何】Minimal Circle

题目

参考博客

参考的楼上博主的思路,我重新理顺了一下思路,用我的话来表达,可能比较好理解 ,楼上博主的表述比较厉害(狗头保命

思路:假设我们在前 i 个点已经确定了一个圆,然后第 i+1个点在圆外面了,那么我们可以知道这个点和前i个点的距离比较远,则我们选择这个点作为圆的边界,然后在前i个点中再选一个点(与其距离最远,假设是第j个点),j和第i+1个点作为圆的直径(这样可以保证第j到第i+1个点全在则个圆内,画图易得),在前j-1个点中遍历,若还有点在圆外,则,和第j,i+1点三点做出一个圆,则这样所有点都在圆内了;

#include <iostream>
#include <cmath>
#include <cstdio>
#include <stdlib.h>
#include <ctime>
#include <algorithm>
#pragma GCC optimize("Ofast","inline","-ffast-math")
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
using namespace std;
const double pi=acos(-1.0);
double r=0;
struct node
{
    double x,y;
}e[105],O;

inline double getdis(node a,node b)
{
    double x=a.x-b.x,y=a.y-b.y;
    return sqrt(x*x+y*y);
}

inline double workO(node p1,node p2,node p3)
{
    double x1=2*(p2.x-p1.x),y1=2*(p2.y-p1.y);
    double c1=p2.x*p2.x+p2.y*p2.y-p1.x*p1.x-p1.y*p1.y;
    double x2=2*(p3.x-p1.x),y2=2*(p3.y-p1.y);
    double c2=p3.x*p3.x+p3.y*p3.y-p1.x*p1.x-p1.y*p1.y;
    O.x=(y1*c2-y2*c1)/(y1*x2-y2*x1);
    O.y=(x2*c1-x1*c2)/(y1*x2-y2*x1);
    return getdis(O,p1);
}

int main()
{
    for(;;)
    {
        int n;cin>>n;
        if(n==0) break;
        for(int i=1;i<=n;i++)  scanf("%lf%lf",&e[i].x,&e[i].y);
        random_shuffle(e+1,e+n+1);
        O=e[1],r=0;
        for(int i=2;i<=n;i++)
        {
            if(getdis(O,e[i])>r)
            {
                O=e[i],r=0;
                for(int j=1;j<=i-1;j++)
                {
                    if(getdis(O,e[j])>r)
                    {
                        O.x=(e[i].x+e[j].x)/2;
                        O.y=(e[i].y+e[j].y)/2;
                        r=getdis(O,e[i]);
                        for(int k=1;k<=j-1;k++)
                        {
                            if(getdis(e[k],O)>r)
                            {
                                r=workO(e[i],e[j],e[k]);
                            }
                        }
                    }
                }
            }
        }
        printf("%.2lf %.2lf %.2lf\n",O.x,O.y,r);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值