模拟退火有什么用?
模拟退火是模拟物理上退火方法,通过N次迭代(退火),逼近函数的上的一个最值(最大或者最小值)。
比如逼近这个函数的最大值C点:(非常大的概率找到最优解)
什么是模拟退火?(基于物理模型)
模拟退火算法的思想借鉴于固体的退火原理,当固体的温度很高的时候,内能比较大,固体的内部粒子处于快速无序运动,当温度慢慢降低的过程中,固体的内能减小,粒子的慢慢趋于有序,最终,当固体处于常温时,内能达到最小,此时,粒子最为稳定。
怎么做?(以求最小值为例)
温度(步长):初始温度$T_0$,终止温度$T_E$,衰减系数$T=T*0.99$,其中,衰减系数在(0,1)中,衰减系数越大,温度衰减越慢,找到最优解的概率越大
1、先随机找一点x0作为当前点 ,不论是哪个点都可以,随机!(不超过定义域就行)
2、每次循环时(即每次降低温度),在所在步长氛围中随机选一个点(温度越大步长越大),$f(新点) - f(旧点) = △E $
情况1:$△E<0$,则一定跳到新点
情况2:$△E>0$,则以一定概率跳去新点,概率是$e^{-\frac{△E}{T}}$(越接近最优解,跳过去的概率最大;越不接近最优解,跳过去的概率越小)
更详细步骤:https://www.cnblogs.com/autoloop/p/15169642.html
-1、提出在保证数据传输的可靠前提下,可以明显降低数据传输的逻辑距离,达到降低网络整体能耗的效果
-2、把信源节点通过中转节点把数据传送到多个目标节点的距离问题,抽象成n个点多边形找费马点位置的模型,使用模拟退火算法计算出费马点位置,
-3、选出最优中转节点,建立节点移动分析模型,建立节点移动路由表
模拟退火求费马点
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <ctime>
#define x first
#define y second
using namespace std;
typedef pair<double, double> PDD;
const int N = 110;
int n;
PDD q[N];
double ans = 1e8;
double rand(double l, double r)
{
return (double)rand() / RAND_MAX * (r - l) + l;
}
double get_dist(PDD a, PDD b)
{
double dx = a.x - b.x;
double dy = a.y - b.y;
return sqrt(dx * dx + dy * dy);
}
double calc(PDD p)
{
double res = 0;
for (int i = 0; i < n; i ++ )
res += get_dist(p, q[i]);
ans = min(ans, res);
return res;
}
void simulate_anneal()
{
PDD cur(rand(0, 10000), rand(0, 10000));
for (double t = 1e4; t > 1e-4; t *= 0.9)
{
PDD np(rand(cur.x - t, cur.x + t), rand(cur.y - t, cur.y + t));//在特定步长的矩形范围内,找随机一个点
double dt = calc(np) - calc(cur);
if (exp(-dt / t) > rand(0, 1)) cur = np;
}
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i ++ ) scanf("%lf%lf", &q[i].x, &q[i].y);
for (int i = 0; i < 100; i ++ ) simulate_anneal();
printf("%.0lf\n", ans);
return 0;
}
大佬,等你补全所有题解呀———Java同学
我也想加入墨染空粉丝团!可以吗(狂逃)
巨弱瑟瑟发抖太强了