zoukankan      html  css  js  c++  java
  • 智能算法(一)——模拟退火,随机化下的贪心

    前言

    贪心,是一个很好的算法,只可惜适用的范围不广。随机化,是一个很好的算法,只可惜正确率不高

    如果将这两个算法结合起来,我们能不能得到一个适用范围广、正确率较高的算法呢?

    答案是肯定的。

    模拟退火((Simulated Annealing),简称(SA)),一个随机化贪心结合的算法,就可以轻松解决许多难题(前提是你的RP较好或是数据范围较小)。

    一个经典的故事

    为了找出地球上最高的山,一群有志气的兔子们开始想办法。

    • 兔子朝着比现在高的地方跳去。它们找到了不远处的最高山峰。但是这座山不一定是珠穆朗玛峰。这就是爬山算法,它不能保证局部最优值就是全局最优值。
    • 兔子喝醉了。他随机地跳了很长时间。这期间,它可能走向高处,也可能踏入平地。但是,它渐渐清醒了并朝最高方向跳去。这就是模拟退火
    • 兔子们知道一个兔的力量是渺小的。它们互相转告着,哪里的山已经找过,并且找过的每一座山他们都留下一只兔子做记号。它们制定了下一步去哪里寻找的策略。这就是禁忌搜索
    • 兔子们吃了失忆药片,并被发射到太空,然后随机落到了地球上的某些地方。它们不知道自己的使命是什么。但是,如果你过几年就杀死一部分海拔低的兔子,多产的兔子们自己就会找到珠穆朗玛峰。这就是遗传算法

    其中第二部分,讲的就是模拟退火

    原理

    类似于物理学上金属退火的过程,故称模拟退火

    主要思路

    我们可以一起来归纳一下模拟退火的主要思路。

    • 首先,我们要先设置一个初始的温度(T)(遵循物理学定律),至于这个初始温度选什么好,我也不太清楚,据说一些大佬可以根据题目推出最优的初始温度。
    • 确定完初温,我们就可以开始操作了。
    • 对于每一个能够从当前状态转移到的下一个状态,我们可以将其与原本的答案进行比较:
    1. 如果(res<new) _ (res),则我们必定转移答案。
    2. 否则,我们有一定概率转移答案(转移答案的概率随时间的推移(res)(new) _ (res)差值的增大而减小),因此我们可以表示为(frac1{exp((res-new\_res)/T)})
    • 最后,在一次答案转移结束后,我们要记得将(T)乘上一个小于但十分接近于(1)的数(delta),以体现时间对答案的影响。

    根据这个主要思路,我们就可以写出模拟退火的模板了:

    int T=***;//给T赋一个初温(我也不知道该赋什么值)
    while(T>eps)//eps是一个大于0的极小值,一般取1e-15
    {
    	int nxt=Next(now),new_res=Calc(nxt);//nxt记录下一个状态,new_res记录下一个状态能得到的答案
    	if(res<new_res||exp((res-new_res)/T)*RAND_MAX>rand()) now=nxt,res=new_res;//如果新的代价小于当前代价,或在一定的几率下,更新当前状态
    	T*=delta;//降温的过程,将温度减小,是一个模拟物理学上的退火操作的过程
    }
    

    例题

    最后,我们一起来看一道例题来感受一下模拟退火的神奇所在:【洛谷1337】[JSOI2004]吊打XXX

    这道题目的正解我也不知道是什么(据说是暴搜?),反正它已经成为了模拟退火的一道经典题。

    题目的大意就是要你求出一张图的广义费马点,具体解析见博客。

  • 相关阅读:
    Vue学习笔记(一)
    Visual Studio Code (vscode)自定义用户代码段快速打出for循环等
    2019.5.5 JS相关
    项目搭建 相关
    2019.4.26 响应式布局
    android The content of the adapter has changed but ListView did not receive a notification 错误的解决方案
    ListView 加载数据时 触摸报错
    android 代码中使用textAppearance
    c/c++ 指针函数 和 函数指针
    c/c++ 指针数组 和 数组指针
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/SimulatedAnnealing.html
Copyright © 2011-2022 走看看