计算几何--最小圆覆盖

给定一些点,求一个圆,可以覆盖所有这些点。

随机增量,每次找一个不在当前圆内的点,将圆调整扩大至该点在圆周上,期望复杂度为O(n)。

调用之前应把点打乱顺序。


#include <iostream>

#include <cstdio>

#include <algorithm>

#include <cmath>

#include <cstdlib>

#include <ctime>

using namespace std;

int mx,my,n;

const int maxn = 1e4 + 5;

const double eps = 1e-8;

struct point{

    double x,y;

    point(double x= 0,double y = 0):x(x),y(y){}

    double dist(){return sqrt(x * x + y * y);}

}p[maxn];

point operator - (const point &a,const point &b){

    return point(a.x - b.x,a.y - b.y);

}

int dcmp(double x){

   return  fabs(x) < eps ? 0 : (x > 0 ? 1 : -1);

}

void circle_center(point p0,point p1,point p2,point &cp){

    double a1 = p1.x - p0.x,b1 = p1.y - p0.y,c1 = (a1 * a1 + b1 * b1) / 2;

    double a2 = p2.x - p0.x,b2 = p2.y - p0.y,c2 = (a2 * a2 + b2 * b2) / 2;

    double d = a1 * b2 - a2 * b1;

    cp.x = p0.x + (c1 * b2 - c2 * b1) / d;

    cp.y = p0.y + (a1 * c2 - a2 * c1) / d;

}

void circle_center(point p0,point p1,point &cp){

    cp.x = (p0.x + p1.x) / 2;

    cp.y = (p0.y + p1.y) / 2;

}

point center;

double radius;


bool point_in(const point &p){

    return dcmp((p - center).dist() - radius) < 0;

}

void min_circle_cover(point a[],int n){

    radius = 0;

    center = p[0];

    for (int i = 1; i< n; i ++) {

        if(!point_in(a[i])){

            center = a[i];radius = 0;

            for (int j = 0; j < i; j ++) {

                if(!point_in(a[j])){

                    circle_center(a[i], a[j], center);

                    radius = (a[j] - center).dist();

                    for (int k = 0; k < j; k ++) {

                        if(!point_in(a[k])){

                        circle_center(a[i], a[j], a[k], center);

                        radius = (a[k] - center).dist();

                        }

                    }

                }

            }

        }

    }

}

int main()

{

    srand(unsigned(time(0)));

    while (scanf("%d%d%d",&mx,&my,&n) != EOF) {

        for (int i = 0; i < n; i ++) {

            scanf("%lf%lf",&p[i].x,&p[i].y);

        }

        random_shuffle(p, p + n);//随机排列数组

        min_circle_cover(p, n);

        printf("(%.1lf,%.1lf).\n",center.x,center.y);

        printf("%.1lf\n",radius);

    }

    return 0;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值