目录
板块一:纸上谈兵
模拟退火算法(Simulated Annealing,SA)1983 年,退火思想引入到组合优化领域。它是基于Monte-Carlo迭代求解策略的一种随机寻优算法,其出发点是基于物理中固体物质的退火过程与一般组合优化问题之间的相似性。模拟退火算法从某一较高初温出发,伴随温度参数的不断下降,结合概率突跳特性在解空间中随机寻找目标函数的全局最优解,即在局部最优解能概率性地跳出并最终趋于全局最优。模拟退火算法是一种通用的优化算法,理论上算法具有概率的全局优化性能,目前已在工程中得到了广泛应用,诸如VLSI、生产调度、控制工程、机器学习、神经网络、信号处理等领域。
模拟退火算法是通过赋予搜索过程一种时变且最终趋于零的概率突跳性,从而可有效避免陷入局部极小并最终趋于全局最优的串行结构的优化算法。
在极值大量出现的时候,可以使用玄学退火方法,参数的调节是否关键。
板块二:总结与板子(不断提纯)
板块三:练习题
第一次学习模拟退火方法,模板的样子不清楚,从理解别人的代码和解题中总结
第一题:run away
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define M_PI 3.14159265358979323846
using namespace std;
#define df 0.85 //冷却比例属于(0, 1)接近1可能会好些
#define maxn 1000
#define maxit 30
#define end 0.001//最终温度
int mx, my;
double fx[maxn], fy[maxn], best[maxn], px[maxn], py[maxn];
double randr(double l, double r) {//生成一个区间的随机数
return (rand() % 10000 / 10000.0 * (r - l) + l);
}
double dist(double x1, double y1, double x2, double y2) {//求距离
return sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}
int main() {
srand(time(NULL));//设定种子
int t, n, res;
cin >> t;
while (t--) {
cin >> mx >> my >> n;//最大的边界和点的数目
for (int i = 0; i < n; i++) {
cin >> px[i] >> py[i];
}
for (int i = 0; i < maxit; i++) {
fx[i] = randr(1, mx);
fy[i] = randr(1, my);//加热乱选30个点
best[i] = inf;
for (int j = 0; j < n; j++) {
best[i] = min(best[i], dist(fx[i], fy[i], px[j], py[j]));
}
}
double step = max(mx, my);//一个足够大温度
while (step > end) {//降温
for (int i = 0; i < maxit; i++) {
for (int j = 0; j < maxit; j++) {
double ag = randr(0, 2 * M_PI);//角度
double nx = fx[i] + step * cos(ag);
double ny = fy[i] + step * sin(ag);
if (nx < 0 || ny < 0 || nx > mx || ny > my) continue;
double d = inf;
for (int k = 0; k < n; k++) {
d = min(d, dist(nx, ny, px[k], py[k]));//获取当前最小距离
}
if (d > best[i]) {//最小值更新
best[i] = d;
fx[i] = nx;
fy[i] = ny;
}
}
}
step *= df;//冷却
}
res = 0;
for (int i = 1; i < maxit; i++) {
if (best[i] >= best[res]) res = i;
}
cout << setiosflags(ios::fixed) << setprecision(1) << "The safest point is (" << fx[res] << ", " << fy[res] << ").\n";
}
return 0;
}