最小圆覆盖问题

 给你一些点,让你求出能够覆盖这些点的最小的圆


思路分析,首先要明确三点就能唯一确定一个圆

(1)将给出的点一个个加入当前最小圆,如果第i点在这个圆内继续,否则转到(2)

(2)首先明确第i点一定在前i个点最小圆的边界上,然后以第i个点为圆心,一次判断前i-1个点是否在这个园内,若j点在圆内继续,若不在圆内则调到(3)

(3)第j点一定在前j(i)个点的最小圆的边界上,然后第i点与j点的中点为圆心,以长度为直径为最小圆继续查找,重新将前j-1个点加入圆,判断是否在圆内,若k在继续,若k不在,则第k个点也在这个圆的边界上,这是就确定三个在边界上的点,就能唯一确定这个圆


最后还需要解决三点如何确定一个圆的问题

先假设这个圆的圆心为(x0,y0),半径为r

则可表示为(x−x0)2+(y−y0)2=r2

三点(x1,y1),(x2,y2),(x3,y3)

则       (x1−x0)2+(y1−y0)2=r2  (1) 

         (x3−x0)2+(y3−y0)2=r2  (2)

       (x2−x0)2+(y2−y0)2=r2   (3)

(1)-(2) (1)-(3)得

(x1−x2)x0+(y1−y2)y0=((x21−x22)−(y22−y21) )/2;

(x1−x3)x0+(y1−y3)y0=((x21−x23)−(y23−y21))/2;

a=x1−x2

b=y1−y2

c=x1−x3

d=y1−y3

e=(x21−x22)−(y22−y21) )/2;

f=((x21−x23)−(y23−y21))/2;

则化简公式

x0=(bf-de)/(bc-ad);

y0=(ce-af)/(bc-ad);

大致代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 100010
using namespace std;
struct node
{
    double x,y;
} b[N];
node O;
double R;
double sqr(double x)
{
    return x*x;
}
double dis(node x,node y)
{
    return sqrt(sqr(x.x-y.x)+sqr(x.y-y.y));
}
bool incircle(node x)
{
    if(dis(O,x)<=R) return true;
    return false;
}
node solve(double a,double b,double c,double d,double e,double f)
{
    double y=(f*a-c*d)/(b*d-e*a);
    double x=(f*b-c*e)/(a*e-b*d);
    return (node)
    {
        x,y
    };
}
int main()
{
    int n;
    while(~scanf("%d",&n)&&n)
    {
        int i,j,k;
        for(i=1; i<=n; i++)
            scanf("%lf%lf",&b[i].x,&b[i].y);
        R=0;
        for(i=1; i<=n; i++)
            if(!incircle(b[i]))
            {
                O.x=b[i].x;
                O.y=b[i].y;
                R=0;
                for(j=1; j<i; j++)
                    if(!incircle(b[j]))
                    {
                        O.x=(b[i].x+b[j].x)/2;
                        O.y=(b[i].y+b[j].y)/2;
                        R=dis(O,b[i]);
                        for(k=1; k<j; k++)
                            if(!incircle(b[k]))
                            {
                                O=solve(
                                      b[i].x-b[j].x,b[i].y-b[j].y,(sqr(b[j].x)+sqr(b[j].y)-sqr(b[i].x)-sqr(b[i].y))/2,
                                      b[i].x-b[k].x,b[i].y-b[k].y,(sqr(b[k].x)+sqr(b[k].y)-sqr(b[i].x)-sqr(b[i].y))/2
                                  );
                                R=dis(b[i],O);
                            }
                    }
            }
        printf("%.2lf %.2lf %.2lf\n",O.x,O.y,R);
    }
}

d

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值