题目链接:https://nanti.jisuanke.com/t/A2141
题目大意:三维空间有n个点,找到另外一个点,离所有点的最大距离最小。求这个距离。和之前的模拟退火的坐标构造方法不同。

初始化 x, y, z 坐标的平均值,然后每次向最远的点移动一定的距离

#include <bits/stdc++.h>
using namespace std;
double x[105], y[105], z[105];
int n;
double ansx=0, ansy=0, ansz=0;
double ans=1e18, t, sx=0, sy=0, sz=0;
const double p=0.98;

double dit(double xx, double yy, double zz, int i){

    return sqrt((x[i]-xx)*(x[i]-xx)+(y[i]-yy)*(y[i]-yy)+(z[i]-zz)*(z[i]-zz));
}

void sim(){

    t=1000;
    while(t>1e-13){
        int px=-1;//距离当前最远点
        double s=-1;//最远距离
        for(int i=1; i<=n; i++){
            if(dit(ansx, ansy, ansz, i)>s){
                s=dit(ansx, ansy, ansz, i);
                px=i;
            }
        }

        ans=min(ans, s);
        ansx=ansx+(x[px]-ansx)*t/1000;//一定概率运动
        ansy=ansy+(y[px]-ansy)*t/1000;
        ansz=ansz+(z[px]-ansz)*t/1000;

        t*=p;
    }
}

void slove(){
    ansx=sx/n, ansy=sy/n, ansz=sz/n;//平均值附件最容易找到最优值
    sim();
    sim();
    sim();
}

int main()
{
    srand(rand());
    scanf("%d", &n);
    for(int i=1; i<=n; i++){
        scanf("%lf%lf%lf", &x[i], &y[i], &z[i]);
        sx+=x[i], sy+=y[i], sz+=z[i];
    }
    slove();
    printf("%.7f\n", ans);

    return 0;
}
/* 3 0 0 0 3 0 0 0 4 0 */