模拟退火(SA)详解
SA——优雅的暴力
-
随机出一个答案:根据题目而变,但一般是随机出的,但是和简单的随机不同,这个答案一般是根据先有的解(注意,不一定是最优解,因为有一定概率我们接受了一个可能更接近最优答案的答案),在此基础随机出的
-
确定接受新状态的概率:见下面代码
模拟退火算法进阶
- 关于参数
模拟退火的参数基本上决定了代码的准确性,一般的, 越高, 越低( ), 越接近 ,模拟退火越准确, 但时间越长,建议在写模拟退火是要卡卡参数
- 关于随机数
模拟退火的精髓就在随机数上,随机数的随机性,循环周期基本上决定了准确度,随机性差,循环周期短的很可能将模拟退火卡掉,建议参考这来优化随机数
-
关于时间
模拟退火是一个不太稳定的算法
(谁叫他随机),单次可能找不到最优解,一般的要多次运行,有一个clock()
函数,返回程序运行时间,建议在不超时的情况下尽可能多跑一般的,可以这样
while((double)clock()/CLOCKS_PER_SEC<=0.8) SA();
(进行模拟退火); -
关于随机化种子
srand((unsigned)time(0)) or srand((int)time(NULL))
-
关于概率接受劣解概率
模板快餐
void SA()
{
double T = 2000;//初始温度
while(T > 1e-10)//退出温度
{
随机生成一个新解
T *= 0.987;//降温
double delta = 原解 - 新解;
if(更优||exp(-(double)delta*RAND_MAX/T) < rand())
/*
关于概率接受劣解的判断条件
exp(-Delta/t)*RAND_MAX<rand() ->> 最大值
exp(-Delta/t)*RAND_MAX>rand() ->> 最小值
*/
{
res = new_res;//接受/一定概率接受
}
}
ans = min(ans,res);//去最值(或其他)
}
最后一点
SA时间复杂度:
写题经验
-
求一个坐标,使其 最大/小
这样退火: double tx=sx+(rand()*2-RAND_MAX)*T; double ty=sy+(rand()*2-RAND_MAX)*T;
-
交换顺序,使其 最大/小
这样退火: int x=rand()%n+1; int y=rand()%n+1; swap(a[x],a[y]);
-
NOIP2021方差,这个比较特殊(退火能拿满分)。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!