很多人都學過貪心,但是貪心在一些情況並不適用,比如:
已知我們從黃色出發,找最小值。
貪心策略當然是一直往函式大小減小的地方偏移——但是,萬一不是單谷呢?我們會陷入如圖的藍色中無法自拔。
肯能你會想到:隨機找乙個點出發,然後貪心找最小值?多隨機幾遍,然後求全域性最小值?
你會發現複雜度暴增!!!!!!!!——所以如何處理這種問題呢?
模擬退火:啊,對對對~
是的!模擬退火就是一種類似於隨機化貪心的乙個演算法,在oi界也小有名氣(冥器)!(如題[noip2021] 方差 )
原理圖:
如圖:在物理應用中分子排布可能是紊亂的,如果我們將它公升溫然後緩慢降溫,就可以生成完美的晶形!
而對於我們求解的:
怎麼形象描述它呢?
乙個有自己一定卡路里的人爬山,他想翻山找遠方的草藥給自己心愛的妻子,但是他並不知道山的那頭是什麼。所以他會在卡路里多的時候盡量去遠方探險,但是每次會花費他的卡路里以至於他後面不能翻過太高的山丘,而且他的揹包蠻大的,裝填著無數愛的草藥芳香四溢。
所以我們立刻(啊,對對對~)能設定模擬退火的引數:
1.初始溫度 t (1000-7000)
2.末尾溫度 p(1e-5~1e-15)
3.降溫係數 k (0.91~0.9975)
4.狀態空間(被降溫物體) s
5.當前能量 e ( new )
6.全域性能量 e ( old )
一:metropolis準則- 以概率接受新狀態:
這就是物理(化學)方面類似的推論——一定概率的更新。
什麼意思呢?
我們已知:當前能量 e ( new ) , 全域性能量 e ( old ),那麼我們的目標是什麼,不就是減少目前的能量嗎?
所以:當當前能量少於全域性能量(即更新前的能量),那麼我們有概率為 1 的更新概率;
當當前能量大於全域性能量(即更新前的能量),那麼我們有概率為 exp( - (e( new )-e( old ))/t) 的更新概率 ( t為當前溫度) [exp(x)函式:e的x次方的函式 如 exp(1)表示e的1次方=e=2.718281828… exp(0)表示e的0次方=1 exp(2)表示e的平方=7.3890561… e是乙個常數,等於2.718281828…];
注意:有時候也不一定以以上方式更新,這只是比較妥的做法,概率方面是可以自己定的,但是一定以當前能量與全域性能量的關係來設定的。(除非直接暴力的隨機演算法)
二:
那麼怎麼生成新的當前溫度呢?,以生成小數為例:
當前將更新溫度=全域性溫度+(rand()*2-rand_max)*t;即:在當前狀態的鄰域結構內以一定概率方式(均勻分布、正態分佈、指數分布等)產生。if(不在狀態空間內)
三:溫度更新函式
若固定每一溫度,演算法均計算至平穩分布,然後下降溫度,則稱為時齊演算法;
若無需各溫度下演算法均達到平穩分布,但溫度需按一定速率下降,則稱為非時齊演算法。
本人用的:
t*=k;四:內迴圈終止準則
本人使用的:
(t>1e-15)//可以改大一點其他常用方法:
(1)設定終止溫度的閾值。
(2)設定外迴圈迭代次數。
(3)演算法搜尋到的最優值連續若干步保持不變。
(4)概率分析方法。
五:實現流程圖:
注意:以下是我自己總結的退火口訣:
初始溫度小心設(1000-3000),又粗又大wa一臉
多次sa更保險,忘了卡時直接t[if((double)clock()/clocks_per_sec>=0.993)]
退火係數大膽設,不過0.9975會很厄
全域性、狀態不一樣,全域性必須菊部優
百年騙分一場空,不開srand見祖宗
退火需謹慎,退火不規範,靈封兩行淚
然後是[noip2021]方差的實現(玄學萬歲):
#include usingnamespace
std;
#define ll long long
const
int n=1e5+10
;const
double dw=0.9975
;int
a[n],n,c[n];
long
long
ans;
bool cmp(int a,int
b)ll en()
for(int i=1;i<=n;i++)em=(long
long)em*n;
for(int i=1;i<=n;i++)ranss=(long
long)ranss*ranss;
return (long
long)(em-ranss);
}void
sa()
int x=rand()%(n-1)+2,y=rand()%(n-1)+2
;
while(x==y)x=rand()%(n-1)+2
; swap(c[x],c[y]);
ll m=en(),dt=ans-m;
if(dt>0
)else
if((double)rand()>=(double)rand_max*(double)exp((double)dt/t))
t*=dw;
}}int
main()
sort(c+2,c+n/2+1
,cmp);
sort(c+n/2+1,c+n+1
); ans=en();
while(1
)sa();
}
模擬退火演算法
w 模擬退火演算法的基本思想 將乙個優化問題比擬成乙個金屬物體,將優化問題的目標函式比擬成物體的能量,問題的解比擬成物體的狀態,問題的最優解比擬成能量最低的狀態,然後模擬金屬物體的退火過程,從乙個足夠高的溫度開始,逐漸降低溫度,使物體分子從高能量狀態緩慢的過渡到低能量狀態,直至獲得能量最小的理想狀態...
模擬退火合集
首次接觸模擬退火 看來還是挺神奇的。主要參考這篇博文 題意判斷多邊形內部能否容納乙個半徑為r的圓,即在有限的平面內找最優範圍。遺傳演算法的結果難以掌控,爬山演算法又沒法保證跳出區域性最優,所以基於貪心原則的模擬退火演算法還是值得考慮的。然後就是設定每次變化的步長和演化方式。該題可以從每條邊的中點開始...
模擬退火演算法
一些求解極值的問題不能通過函式特性直接求解,只能暴力列舉,但是單純的列舉效率不高,通過模擬退火演算法可以高效的找到答案。學習好博文 最小圓覆蓋 hdu 3007 buried memory 大意 給出一些點,求出能覆蓋他們的最小的圓。輸出圓心和半徑 include include include i...