【计算几何】最小圆覆盖
2021-03-09 16:58:00 # ACM
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#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;
}
Prev
2021-03-09 16:58:00 # ACM
Next