1. 程式人生 > 其它 >【資料結構】演算法 搜尋旋轉排序陣列 Search in Rotated Sorted Array II

【資料結構】演算法 搜尋旋轉排序陣列 Search in Rotated Sorted Array II

模擬退火

問題引入

\,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
$$

就可以做到隨機接受了