[gym101981D][2018ICPC南京D题]Country Meow

题目链接

题目大意是求三维空间可以包含$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 }

猜你喜欢

转载自www.cnblogs.com/sainsist/p/11622860.html