最小圆覆盖

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int MAXN = 5009;

int N;
struct Point {
    double x, y;
}p[MAXN], C; // p[i] 表示点集 ,C = {x,y} 表示圆心 
double R; // 圆 半径  

double sqr(double x) {
    return x * x;
}

double dis(Point a, Point b) {
    return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));
}

void MakeC(Point p1, Point p2, Point p3) {
    double a = p2.x - p1.x,
           b = p2.y - p1.y,
           c = p3.x - p1.x,
           d = p3.y - p1.y,
           e = (sqr(p2.x) - sqr(p1.x) + sqr(p2.y) - sqr(p1.y)) / 2,
           f = (sqr(p3.x) - sqr(p1.x) + sqr(p3.y) - sqr(p1.y)) / 2;
    C.x = (e * d - b * f) / (a * d - b * c);
    C.y = (a * f - e * c) / (a * d - b * c);
    R = dis(C, p1);
}

double cal(){
	random_shuffle(p + 1, p + N + 1);
    for(int i = 1; i <= N; i++) {
        if(dis(p[i], C) < R) continue;
        C = p[i]; R = 0;
        for(int j = 1; j <= i - 1; j++) {
            if(dis(p[j], C) < R) continue;
            C.x = (p[i].x + p[j].x) / 2.0;
            C.y = (p[i].y + p[j].y) / 2.0;
            R = dis(C, p[j]);
            for(int k = 1; k <= j - 1; k++) {
                if(dis(p[k], C) < R) continue;
                MakeC(p[i], p[j], p[k]);
            }
        }
    }
    return R;
}

void init(){
	R = 0;
	C = {0,0};
}

int main() {
    scanf("%lld",&N);
    
    for(int i = 1; i <= N; i++){
    	scanf("%lf %lf",&p[i].x,&p[i].y);
	}
	init();
	double ans = cal();

    printf("%.10f\n",ans);
    
    return 0;
}
posted @ 2021-03-09 16:58  棉被sunlie  阅读(60)  评论(0)    收藏  举报