2018 ICPC Nanjing D. Country Meow ,最小球覆盖,模拟退火
题意
给定(N) 个点,求一个点使得到这(N)个点中最大距离最小,求出这个距离
[1leq N leq 100,-100000leq x_i,y_i,z_i leq 100000
]
分析
容易想到这是一个最小球覆盖问题,这个问题和最小圆覆盖都可以用模拟退化解决。
每次贪心地靠近最远距离即可。
注意这里更新坐标与之前的模拟退化有点不太一样
代码
struct Point {
double x, y, z;
};
Point p[105];
double get_dis(Point a, Point b) {
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z));
}
const double beginT = 10000, endT = 1e-12, delT = 0.99;
int n;
double ans;
void SA(int times) {
Point pp;
pp.x = pp.y = pp.z = 0;
int s = 0 ;
ans = 1e18;
while (times--) {
for (double T = beginT; T >= endT; T *= delT) {
for (int i = 1; i <= n; i++)
if (get_dis(pp, p[i]) > get_dis(pp, p[s])) s = i;
double d = get_dis(p[s], pp);
ans = min(ans, d);
pp.x += (p[s].x - pp.x) * T / beginT;
pp.y += (p[s].y - pp.y) * T / beginT;
pp.z += (p[s].z - pp.z) * T / beginT;
}
}
}
int main() {
n = readint();
for (int i = 1; i <= n; i++) scanf("%lf%lf%lf", &p[i].x, &p[i].y, &p[i].z);
SA(10);
printf("%.8f", ans);
}