模拟退火


模拟退火伪代码:

/*
* J(y):在状态y时的评价函数值
* Y(i):表示当前状态
* Y(i+1):表示新的状态
* r: 用于控制降温的快慢
* T: 系统的温度,系统初始应该要处于一个高温的状态
* T_min :温度的下限,若温度T达到T_min,则停止搜索
*/
while( T > T_min )
{
  dE = J( Y(i+1) ) - J( Y(i) ) ; 

  if ( dE >=0 ) //表达移动后得到更优解,则总是接受移动
Y(i+1) = Y(i) ; //接受从Y(i)到Y(i+1)的移动
  else
  {
// 函数exp( dE/T )的取值范围是(0,1) ,dE/T越大,则exp( dE/T )也
if ( exp( dE/T ) > random( 0 , 1 ) )
Y(i+1) = Y(i) ; //接受从Y(i)到Y(i+1)的移动
  }
  T = r * T ; //降温退火 ,0<r<1 。r越大,降温越慢;r越小,降温越快
  /*
  * 若r过大,则搜索到全局最优解的可能会较高,但搜索的过程也就较长。若r过小,则搜索的过程会很快,但最终可能会达到一个局部最优值
  */
  i ++ ;
}

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;
}

Luogu P1337

LL x[maxn], y[maxn], w[maxn];
int n;
double ans, xx, yy;
double dis(double X, double Y) {
	double res = 0.0;
	for (int i = 1; i <= n; i++) {
		res += sqrt((x[i] - X)*(x[i] - X) + (y[i] - Y)*(y[i] - Y))*w[i];
	}
	return res;
}
void SA() {
	double x, y, z, res;
	double T = 20001, D = 0.993;//初始温度 退火率
	while (T > 1e-14) {
		//根据最优解随机一个变动值随着T缩小范围
		x = xx + ((rand() << 1) - RAND_MAX)*T;//rand的范围变成(-rand_max,rand_max)
		y = yy + ((rand() << 1) - RAND_MAX)*T;
		res = dis(x, y);
		if (res < ans)//更新最优解
			ans = res, xx = x, yy = y;
		else if (exp((ans - res) / T)*RAND_MAX > rand())//概率接受当前解
			xx = x, yy = y;
		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] >> w[i];
		xx += 1.0*x[i], yy += 1.0*y[i];
	}
	xx /= 1.0*n, yy /= 1.0*n;
	ans = dis(xx, yy);
	for (int i = 1; i <= 5; i++)
		SA();
	printf("%.3lf %.3lf\n", xx, yy);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值