[POJ2069]Super Star(模拟退火)

题目链接:http://poj.org/problem?id=2069

题意:求一个半径最小的球,使得它可以包围住所有点。

模拟退火,圆心每次都去找最远那个点,这样两点之间的距离就是半径,那么接下来移动的方向肯定就是朝着这个最远点移动,保证比例相同且在球内的情况下移动。

不看题解想不到,这个东西有点难啊。。。

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <iomanip>
 4 #include <cstring>
 5 #include <climits>
 6 #include <complex>
 7 #include <cassert>
 8 #include <cstdio>
 9 #include <bitset>
10 #include <vector>
11 #include <deque>
12 #include <queue>
13 #include <stack>
14 #include <ctime>
15 #include <set>
16 #include <map>
17 #include <cmath>
18 using namespace std;
19 
20 typedef struct P {
21     double x, y, z;
22 }P;
23 const double inf = 1e90;
24 const double eps = 1e-7;
25 const double delta = 0.98;
26 const int maxn = 55;
27 P p[maxn];
28 int n;
29 
30 double dist(P a, P b) {
31     double p = a.x - b.x;
32     double q = a.y - b.y;
33     double r = a.z - b.z;
34     return sqrt(p*p+q*q+r*r);
35 }
36 
37 int main() {
38     // freopen("in", "r", stdin);
39     while(~scanf("%d", &n) && n) {
40         for(int i = 0; i < n; i++) {
41             scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z);
42         }
43         double t = 100;
44         double ret = inf;
45         P pos = {0, 0, 0};
46         while(t > eps) {
47             int k = 0;
48             for(int i = 0; i < n; i++) {
49                 if(dist(pos, p[i]) > dist(pos, p[k])) {
50                     k = i;
51                 }
52             }
53             double d = dist(pos, p[k]);
54             ret = min(ret, d);
55             pos.x += (p[k].x - pos.x) / d * t;
56             pos.y += (p[k].y - pos.y) / d * t;
57             pos.z += (p[k].z - pos.z) / d * t;
58             t *= delta;
59         }
60         printf("%.5lf\n", ret);
61     }
62     return 0;
63 }

 

posted @ 2016-12-28 17:12  Kirai  阅读(202)  评论(0编辑  收藏  举报