题目大意是求三维空间可以包含$n$个点的最小圆半径。
如果有做过洛谷P1337就会发现这到题很模拟退火,所以就瞎搞一发。
$PS:$注意本题时限$3$秒。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 2111; 5 struct node { 6 double x, y, z; 7 }a[maxn]; 8 int n; 9 double ansx, ansy, ansz, ans; 10 double dis(double x, double y, double z, node w) { 11 return sqrt((x - w.x) * (x - w.x) + (y - w.y) * (y - w.y) + (z - w.z) * (z - w.z)); 12 } 13 double solve(double x, double y, double z) { 14 double w = 0; 15 for (int i = 1; i <= n; i++) 16 w = max(w, dis(x, y, z, a[i])); 17 return w; 18 } 19 const double delta = 0.998; 20 void SA() { 21 double X = ansx, Y = ansy, Z = ansz; 22 double t = 1999; 23 while (t > 1e-14) { 24 double x = X + (rand() * 2 - RAND_MAX) * t; 25 double y = Y + (rand() * 2 - RAND_MAX) * t; 26 double z = Z + (rand() * 2 - RAND_MAX) * t; 27 double now = solve(x, y, z); 28 double D = now - ans; 29 if (D < 0) { 30 X = x, Y = y, Z = z; 31 ansx = X, ansy = Y; 32 ansz = Z; 33 ans = now; 34 } 35 else if (exp(-D / t) * RAND_MAX > rand())X = x, Y = y, Z = z; 36 t *= delta; 37 } 38 } 39 int main() { 40 srand(unsigned(time(NULL))); 41 scanf("%d", &n); 42 for (int i = 1; i <= n; i++) { 43 scanf("%lf%lf%lf", &a[i].x, &a[i].y, &a[i].z); 44 ansx += a[i].x, ansy += a[i].y, ansz += a[i].z; 45 } 46 ansx /= n, ansy /= n, ansz /= n; 47 ans = solve(ansx, ansy, ansz); 48 while ((double)clock() / CLOCKS_PER_SEC < 2.7) 49 SA(); 50 printf("%.10f", ans); 51 }