真正的人品永远无惧于参数的调控
模拟退火
模拟退火算法来源于固体退火原理,是一种基于概率的算法,将固体加温至充分高,再让其徐徐冷却,加温时,固体内部粒子随温升变为无序状,内能增大,而徐徐冷却时粒子渐趋有序,在每个温度都达到平衡态,最后在常温时达到基态,内能减为最小。
——百度百科
换句话说,固体的冷却就相似于一个多峰函数,而最后内能最小的状态,就是一整个函数的最小值。
模拟退火实际上模拟的就是这个过程。我们给他设置一个初始温度 T 0 T_0 T0(足够大),在设置一个降温系数 δ \delta δ(略小于1),在设置一个终止温度,越小越精确。
首先让我们让温度等于 T 0 T_0 T0,随机出一个解 S S S。然后我们让 T 0 = T 0 ∗ δ T_0=T_0*\delta T0=T0∗δ,每次降温,我们都随机出另一个随机解状态 S ′ S' S′,假如 S > S ′ S>S' S>S′,说明新的解更好,我们就直接接受新解,如果 S < S ′ S<S' S<S′,我们设置一个概率 e x p ( − Δ T / T ) exp(-ΔT/T) exp(−ΔT/T)去接受这个解,从而赋予模拟退火算法跳出局部最优解的能力。
解状态 S S S根据题意而定。
代码:
int SA()//模拟退火
{
double t=10000,now=ans,xz=0.97;
while(t>0.0001)
{
int x=rand()%n+1,y=rand()%n+1;//随机匹配
swap(A[x],A[y]); //随机到另一个状态
double res=calc(); //算出此时的解
if(res<now ||exp(-ch)/t>(double)(rand()%100/100.00))
now=res; //更改最优解
else
swap(A[x],A[y]); //不转移解的话就把状态换回来
t*=xs;
}
}
这里的clac和状态转移都是因题而异的。
例题:LuoguP2503