模拟退火
模拟退火
问题引入
个有维性质以及价值的物品,放入个有维限制的背包中,求总价值最大值
爬山&贪心
这题有一个显而易见的错误做法,先把物品按某种神秘方式排序,然后贪心地放入背包
于是考虑乱搞,每次random_shuffle一下物品,再重新计算,取历史最优解,正确率就得到提高了,但期望得到正解的次数是级别的,和暴力没有区别
考虑优化,发现这是因为没有利用之前贪心得到的一些优秀特征,比如有一个没有代价的物品被移来移去就是毫无意义的
由此可以发现,应当减少每次移动的数量,把random_shuffle变成swap,这样效率没有改变,但是按神秘方式排序后得到正确结果的概率提高了,耗费在移动上的时间也减少了
模拟退火
随贪乱搞显然是不行的,必须继续优化,发现随机swap依然可能导致优秀特征的随机损失或无效的交换
为了避免这一问题,模拟退火以一定概率接受随机的修改
分两种情况考虑:
新解优于历史最优解:当然接受这次修改
新解不优于历史最优解:以的概率接受新解
表示新解与历史最优解的差,是模拟退火的一个可变参数,具体地,
是一个常数,取值通常在,用来更新,也就是当前温度
这样比完全随机接受优是因为表明答案劣化的越少越容易接受,的设置则使得接受新解的概率越来越小,使得算法越来越接近朴素爬山
名字叫模拟退火是因为从物理上固体退火得到的启发
模板:
calc();//计算新解
renew();//随机刷新
recover();//还原刷新
SA()
{
auto tmp;
double T=;
while(T>=eps)
{
renew();
tmp=calc();//临时答案
if(better(tmp,ans)) ans=tmp;//如果更优
else if(exp((tmp-ans)/T)*RAND_MAX<=rand()) recover();//有可能接受
T*=delta;//刷新温度
}
}
while(clock()<=CLOCKS_PER_SEC*MAX_TIME) SA();//卡时调用,MAX_TIME比题目时限小一点
解释一下
就可以做到随机接受了
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现