模拟退火、爬山

模拟退火

模拟退火算法(Simulate Anneal,SA)是一种基于随机化的乱搞算法,常用于解决求解多峰函数最大值。

常见处理问题有:平面最小能量点(如 P1337 [JSOI2004]平衡点 / 吊打XXXP5544 [JSOI2016]炸弹攻击1)、最优分配或随机分配最大收益(如 P3878 [TJOI2010]分金币)等等。

其中最为核心的就是模拟金属退火的操作,我们对答案接受的可能性随着温度的降低而减少,大致代码如下:

inline void sa()
{
	double t=5000.0,cool=0.996,eps=1e-15;
	while(t>eps)
	{
		double tx=ansx+(rand()*2-RAND_MAX)*t;
		double ty=ansy+(rand()*2-RAND_MAX)*t;
		int Now=calc(tx,ty);
		double de=Now-ans; // 这里求解的是最大值 
		if(de>0) ans=Now,ansx=tx,ansy=ty;
		else if(exp(-de/t)*RAND_MAX<rand())
			ansx=tx,ansy=ty;
		// 若需要求解最小值,将上面两个 if 的不等号取反 
		t*=cool;
	}
}

其他例题:P3936 ColoringP2538 [SCOI2008]城堡P2210 Haywire

关于参数的一些小问题:可以设初始温度在 \(\texttt{3000}^\circ\),下降温度比例约为 \(\texttt{0.996}\)\(\texttt{eps}\) 设为 \(\texttt{1e-12}\)

如果发现正确性不够,可以多跑几次,不用更改上面的温度等。

posted @ 2021-10-08 11:03  EricQian06  阅读(34)  评论(0编辑  收藏  举报