目录
模拟退火伪代码:
/*
* 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;
}