模拟退火
问题引入
\(\,n\,\)个有\(\,k\,\)维性质以及价值\(\,w\,\)的物品,放入\(\,m\,\)个有\(\,k\,\)维限制的背包中,求总价值最大值
爬山&贪心
这题有一个显而易见的错误做法,先把物品按某种神秘方式排序,然后贪心地放入背包
于是考虑乱搞,每次random_shuffle一下物品,再重新计算,取历史最优解,正确率就得到提高了,但期望得到正解的次数是\(\,n!\,\)级别的,和暴力没有区别
考虑优化,发现这是因为没有利用之前贪心得到的一些优秀特征,比如有一个没有代价的物品被移来移去就是毫无意义的
由此可以发现,应当减少每次移动的数量,把random_shuffle变成swap,这样效率没有改变,但是按神秘方式排序后得到正确结果的概率提高了,耗费在移动上的时间也减少了
模拟退火
随贪乱搞显然是不行的,必须继续优化,发现随机swap依然可能导致优秀特征的随机损失或无效的交换
为了避免这一问题,模拟退火以一定概率接受随机的修改
分两种情况考虑:
新解优于历史最优解:当然接受这次修改
新解不优于历史最优解:以\(e^{\frac{\Delta f}{T}}\)的概率接受新解
\(\,\Delta f\,\)表示新解与历史最优解的差,\(\,T\,\)是模拟退火的一个可变参数,具体地,
\[T_{next\,\,time}=T_{now}*\delta \]\(\,\delta\,\)是一个常数,取值通常在\(\,[0.98,1]\,\),用来更新\(\,T\,\),也就是当前温度
这样比完全随机接受优是因为\(\,\Delta f\,\)表明答案劣化的越少越容易接受,\(\,T\,\)的设置则使得接受新解的概率越来越小,使得算法越来越接近朴素爬山
名字叫模拟退火是因为从物理上固体退火得到的启发
模板:
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比题目时限小一点
解释一下
\[e^{\frac{\Delta f}{T}}\,\ast\,RAND\,MAX\leq rand()\rightarrow e^{\frac{\Delta f}{T}}\leq 0.5 \]就可以做到随机接受了
标签:tmp,Delta,新解,模拟退火,随机,ans 来源: https://www.cnblogs.com/efX-bk/p/15421707.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。