正在计算几何入门中。。。。。。
这道题就是求最小圆覆盖。题目讲了这么多,只有6个字
对于1个点,它的最小覆盖圆是一个点。对于2个点,它们的最小覆盖圆是以它们为直径的圆。
首先考虑已知i个点被最小的圆O覆盖,若第i+1个点在圆O内,显然这i+1个点的最小覆盖圆也是O。若第i+1个点不在圆O内,设圆O1是i+1个点的最小覆盖圆。可以证明这个点在圆O1上。
然后对于点i+1,不断加入1~i的点,同样的方法可以求得另一个在圆O1上的点j。
最后固定这两个点,再不断加入1~i的点,可以得到圆O1上的3个点,于是就可以得到圆O1。
注意:圆上可以只有2个点,如钝角三角形的三个顶点。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#define Hz 1e-6
using namespace std;
struct dot{double x,y;}a[1000005],O;
int n;double R;
double sqr(double x)
{
return x*x;
}
double dis(dot a,dot b)//求距离
{
return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}
dot getO(dot a,dot b)//已知2点求圆心
{
dot k;
k.x=(a.x+b.x)/2;
k.y=(a.y+b.y)/2;
return k;
}
dot getO(dot a,dot b,dot c)//已知3点求圆心
{
double x1=-2*(a.x-b.x);
double y1=-2*(a.y-b.y);
double z1=a.x*a.x+a.y*a.y-b.x*b.x-b.y*b.y;
double x2=-2*(b.x-c.x);
double y2=-2*(b.y-c.y);
double z2=b.x*b.x+b.y*b.y-c.x*c.x-c.y*c.y;
dot k;
k.x=(y1*z2-z1*y2)/(x1*y2-x2*y1);
k.y=(x1*z2-z1*x2)/(y1*x2-y2*x1);
return k;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%lf%lf",&a[i].x,&a[i].y);//输入时可进行随机处理,本题数据未特殊处理
O=a[1];R=0;
for (int i=1;i<=n;i++)
{
if (dis(O,a[i])<=R+Hz) continue;
O=getO(a[1],a[i]);R=dis(O,a[i]);
for (int j=1;j<i;j++)
{
if (dis(O,a[j])<=R+Hz) continue;
O=getO(a[i],a[j]);R=dis(O,a[i]);
for (int k=1;k<j;k++)
{
if (dis(O,a[k])<=R+Hz) continue;
O=getO(a[i],a[j],a[k]);R=dis(O,a[i]);
}
}
}
printf("%.2f %.2f %.2f\n",O.x,O.y,R);
return 0;
}