模板:模擬退火
阿新 • • 發佈:2021-01-20
double ansx,ansy; //全域性最優解的座標
double ans=1e18,t; //全域性最優解、溫度
const double delta=0.993; //降溫係數
inline double calc_energy() { //計算整個系統的能量
return 0;
}
void simulate_anneal() { //SA主過程
double x=ansx,y=ansy;
t=2000; //初始溫度
while (t>1e-14) {
double X=x+((rand()<<1)-RAND_MAX) *t;
double Y=y+((rand()<<1)-RAND_MAX)*t; //得出一個新的座標
double now=calc_energy();
double Delta=now-ans;
if (Delta<0) { //接受
x=X,y=Y;
ansx=x,ansy=y,ans=now;
}
else if (exp(-Delta/t)*RAND_MAX>rand()) x=X,y=Y; //以一個概率接受
t*= delta;
}
}
inline void Solve() { //多跑幾遍SA,減小誤差
ansx=(double)sx/n,ansy=(double)sy/n; //從平均值開始更容易接近最優解
simulate_anneal();
simulate_anneal();
simulate_anneal();
}
//#include <bits/stdc++.h>
#include <math.h>
#include <cstdio>
#include <iostream>
#include <cstring>
#define int long long
using namespace std;
const int mod = 1e9+7;
struct node{
double x,y,z;
}p[1005];
int n;
double dis(double xx,double yy,double zz,int i){
double x = xx-p[i].x;
double y = yy-p[i].y;
double z = zz-p[i].z;
return sqrt(x*x+y*y+z*z);
}
double sa(){
double EPS = 1e-9;
double T = 100000;
double delta = 0.98;
double res = 1e18;
double x = 0,y = 0,z = 0;
while(T > EPS){
double diss = 0;
int d = 0;
for(int i = 0 ; i < n ; i ++){
double tmp = dis(x,y,z,i);
if(tmp > diss){
diss = tmp;
d = i;
}
}
res = min(res,diss);
x += (p[d].x - x)/diss*delta*T;
y += (p[d].y - y)/diss*delta*T;
z += (p[d].z - z)/diss*delta*T;
T *= delta;
}
return res;
}
signed main(){
while(~scanf("%lld",&n) && n){
for(int i = 0 ; i < n ; i ++)
scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z);
printf("%.15f\n",sa());
}
return 0;
}