题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3932
题意:题目大意:
给出 N(1<=N<=100)个点,求一个半径最小的圆,使得这个圆可以覆盖所有的
点。
solution:
#include <bits/stdc++.h>
using namespace std;
#define eps 1e-8
int n;
double X, Y, R;
struct Point{
double x, y;
Point() = default;
Point(double x, double y){
this->x = x;
this->y = y;
}
bool check(){
if (x + eps > 0 && y + eps > 0 && x < eps + X && y < eps + Y)return true;
return false;
}
}p[1005], central;
//求三点的外接圆圆心
Point Circumcenter(Point a, Point b, Point c){
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;
return Point(a.x + (c1 * b2 - c2 * b1) / d, a.y + (a1 * c2 - a2 * c1) / d);
}
//求距离
double dis(Point a, Point b){
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
//将点随机化
void MinCoverCircle()
{
random_shuffle(p, p + n);//随机洗牌
central = p[0];
R = 0;
//假设前i个点已经构成了最小圆覆盖
for (int i = 1; i < n; ++i)
{
if (dis(central, p[i]) + eps > R){
central = p[i];
R = 0;
for (int j = 0; j < i; ++j){
if (dis(central, p[j]) + eps > R){
central.x = (p[i].x + p[j].x) / 2;
central.y = (p[i].y + p[j].y) / 2;
R = dis(central, p[j]);
for (int k = 0; k < j; ++k){
//三点确定圆
if (dis(central, p[k]) + eps > R){
central = Circumcenter(p[i], p[j], p[k]);
R = dis(central, p[k]);
}
}
}
}
}
}
}
int main()
{
while (cin >> X >> Y >> n){
for (int i = 0; i < n; ++i)scanf("%lf%lf", &p[i].x, &p[i].y);
MinCoverCircle();
printf("(%.1f,%.1f).\n%.1f\n", central.x, central.y, R);
}
return 0;
}