给你一些点,让你求出能够覆盖这些点的最小的圆
思路分析,首先要明确三点就能唯一确定一个圆
(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
#include
#include
#include
#include
#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 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
{
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