背景:想象整个解空间为一段连续的函数,y轴为温度,求解的过程相当于求一个全局的最优解。
模拟退火有关的几个概念:
温度(步长): 初始温度
T
0
T_0
T0,终止温度
T
E
T_E
TE
衰减系数:
T
′
=
T
∗
0.96
T'=T * 0.96
T′=T∗0.96, 这个0.96就是一个衰减系数,取值为(0,1)之间的一个值,一般来说,系数越大,搜到全局最优解的可能最大。
温度差
△
E
\bigtriangleup E
△E: 新点
T
2
T_2
T2和当前点
T
1
T_1
T1的温度差。
△
E
=
T
2
−
T
1
\bigtriangleup E=T_2-T_1
△E=T2−T1
局部最优解: 记当前函数为
f
(
x
)
f(x)
f(x) ,
x
0
x_0
x0满足
f
′
(
x
0
)
=
0
f'(x_0)=0
f′(x0)=0,
f
′
′
(
x
0
)
>
0
f''(x_0)>0
f′′(x0)>0的所有点。
步骤:
- 确定若干个点作为初始温度 T 0 T_0 T0,开始搜索
- 从当前温度附近的区间选择一个新点,温度为
T
1
T_1
T1,开始下一步的搜索。
- △ E < 0 \bigtriangleup E<0 △E<0时,往新点搜索
- △ E > 0 \bigtriangleup E>0 △E>0时,以一定概率往新点搜索,这个概率的经验值为 P ( x ) = e − △ E T P(x)=e^{-{\frac{\bigtriangleup E}{T}}} P(x)=e−T△E。可以看出, △ E \bigtriangleup E △E越大时,往这个点搜索的概率越小
题目
#include<iostream>
#include<ctime>
#include<cmath>
using namespace std;
typedef pair<double, double> PDD;
#define x first
#define y second
const int N = 110;
int n;
PDD p[N];
double ans = 1e18;
//产生l,r之间的一个随机数字
double rand(double l, double r) {
return (double)rand() / RAND_MAX * (r - l) + l;
}
double get_dis(PDD pt) {
double res = 0;
for(int i = 0; i < n; i++) {
double dx = p[i].x - pt.x, dy = p[i].y - pt.y;
res += sqrt(dx * dx + dy * dy);
}
ans = min(res, ans);
return res;
}
void simulate_anneal() {
PDD cur(rand(0, 1e4), rand(0, 1e4));
for(double t = 1e4; t > 1e-4; t *= 0.99) {
PDD np(rand(cur.x - t, cur.x + t), rand(cur.y - t, cur.y + t));
double delta = get_dis(np) - get_dis(cur);
if(exp(-delta / t) > rand(0, 1)) cur = np;
}
}
int main()
{
scanf("%d", &n);
for(int i = 0; i < n; i++) scanf("%lf%lf", &p[i].x, &p[i].y);
for(int i = 0; i < 100; i++) {
simulate_anneal();
}
printf("%.0lf\n", ans);
return 0;
}
class Solution {
public:
int w[31], n;
int m, ans;
int calc() {
int res = 0;
for(int i = 0, s = 0; i < n; i++) {
if(!s) res++;
s = (s + w[i]) % m;
}
ans = max(ans, res);
return res;
}
void simualate_anneal() {
random_shuffle(w, w + n);
for(double t = 1e6; t > 1e-5; t *= 0.98) {
int a = rand() % n, b = rand() % n;
int x = calc();
swap(w[a], w[b]);
int y = calc();
int delta = x - y;
if(!(exp(-delta /t) > (double)rand() / RAND_MAX)) swap(w[a], w[b]);
}
}
int maxHappyGroups(int batchSize, vector<int>& groups) {
m = batchSize;
for(int x: groups) w[n++] = x;
for(int i = 0; i < 100; i++) {
simualate_anneal();
}
return ans;
}
};