三分待补…
2018ic南京D. Country Meow
模拟退火代码:
LL x[maxn], y[maxn], z[maxn];
int n;
double ans, xx, yy, zz;
double lon(double x1, double x2, double y1, double y2, double z1, double z2) {
double res = 0.0;
res += 1.0*(x1 - x2)*(x1 - x2);
res += 1.0*(y1 - y2)*(y1 - y2);
res += 1.0*(z1 - z2)*(z1 - z2);
return sqrt(res);
}
double dis(double X, double Y, double Z) {
double res = 0.0;
for (int i = 1; i <= n; i++) {
res = max(res, lon(X, x[i], Y, y[i], Z, z[i]));
}
return res;
}
void SA() {
double x, y, z, res;
double T = 4, D = 0.995;//初始温度 退火率
while (T > 1e-8) {
//根据最优解随机一个变动值随着T缩小范围
x = xx + ((rand() << 1) - RAND_MAX)*T;//rand的范围变成(-rand_max,rand_max)
y = yy + ((rand() << 1) - RAND_MAX)*T;
z = zz + ((rand() << 1) - RAND_MAX)*T;
res = dis(x, y, z);
if (res < ans)//更新最优解
ans = res, xx = x, yy = y, zz = z;
else if (exp((ans - res) / T)*RAND_MAX > rand())//概率接受当前解
xx = x, yy = y, zz = z;
T *= D;//退火
}
}
int main()
{
srand(time(NULL) * 11);
rand();//随机化种子
cin >> n;
//ans = sqrt(3.0)*100000.0 + 1000.0;
for (int i = 1; i <= n; i++) {
cin >> x[i] >> y[i] >> z[i];
xx += 1.0*x[i], yy += 1.0*y[i], zz += 1.0*z[i];
}
xx /= 1.0*n, yy /= 1.0*n, zz /= 1.0*n;
ans = dis(xx, yy, zz);
SA();
printf("%.15lf\n", ans);
return 0;
}