2018ic南京D. Country Meow(模拟退火、三分)

三分待补…
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;
}

Guess you like

Origin blog.csdn.net/weixin_44986601/article/details/111054191