【資料結構】演算法 搜尋旋轉排序陣列 Search in Rotated Sorted Array II
阿新 • • 發佈:2021-10-14
問題引入
\,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
$$