最小圆覆盖定义:给出n个点,找出一个最小的圆,圆内包含所有的点。
先给出代码,后续证明+自己的想法。
板子题是HDU 3007
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=5e2+10;
struct node
{
double x,y;
}p[maxn];
double dis(node a,node b)//距离
{
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
node getcircle(node a,node b,node c)//获取外心//中垂线方程以及直线方程交点求出
{ node o;
double a1 = b.x - a.x, b1 = b.y - a.y, c1 = (a1 * a1 + b1 * b1) / 2;
double a2 = c.x - a.x, b2 = c.y - a.y, c2 = (a2 * a2 + b2 * b2) / 2;
double d = a1 * b2 - a2 * b1;
o.x = a.x + (c1 * b2 - c2 * b1) / d;
o.y = a.y + (a1 * c2 - a2 * c1) / d;
return o;
}
int main()
{
int n;
while(~scanf("%d",&n)&&n)
{
for(int i=1;i<=n;i++)
{
scanf("%lf %lf",&p[i].x,&p[i].y);
}
double r=0;
node o=p[1];
for(int i=1;i<=n;i++)
{
if(dis(p[i],o)>r)
{
r=0;
o=p[i];
for(int j=1;j<i;j++)//第二个点
{
if(dis(p[j],o)>r) //如果这个点不在Ci-1上,那么pj肯定在新圆的边上
{
o.x=(p[j].x+p[i].x)/2;
o.y=(p[j].y+p[i].y)/2;
r=dis(p[j],o);
for(int k=1;k<j;k++)//第三个点
{
if(dis(p[k],o)>r)//如果这个点不在Ci-1上,那么这个点肯定在Ci的边上
{
o=getcircle(p[i],p[j],p[k]);
r=dis(p[k],o);
}
}
}
}
}
}
printf("%.2lf %.2lf %.2lf\n",o.x,o.y,r);
}
return 0;
}