[蒟蒻實驗室]Ep.1背包退火!
阿新 • • 發佈:2018-12-16
max arch else archive false warn 當前 ans html 首先就是模擬退火的隨機設置自然就是把隨機數種子設置好,
該過程通過降溫系數delta對初溫為T的物體降溫,直到物體溫度冷卻接近0。但是不能直接將tot作為答案輸出,否則
5.交一次不行說明
[蒟蒻實驗室]Ep.1背包退火!
· FBI Warning
· 新算法:背包退火!
· 本文所包含的思路來自於NCC79601巨佬的啟迪Orz
·算法剖析
簡單來講,背包退火就是用模擬退火的思路解決某些類型的背包問題,繼承了模擬退火的玄學復雜度,也繼承了它的不穩定性,所以能夠有效地解決大背包問題的TLE問題。這個算法能夠把數十行的代碼優化部分轉移為 洗把臉 調參的問題。
例題 :LuoGuP1049【裝箱問題】
有一個箱子容量為V,同時有n個物品,每個物品有一個體積vi。要求n個物品中,任取若幹個裝入箱內,使箱子的剩余空間為最小。
·算法過程
首先就是模擬退火的隨機設置自然就是把隨機數種子設置好,別忘了先洗臉 ,然後通過模擬退火原理設置好轉移概率表達式:
1 bool accept(int del) 2 { 3 return ((del>0)||exp(-del/T) > (double)rand()/RAND_MAX); 4 } //轉移概率表達式
然鵝蒟蒻的我很難解釋清楚為什麽隨著T的減小他接受更劣解的概率會越來越小,只知道利用這個概率是e^(-dE/kT)。
使用這個概率從而達到剛開始退火,跳出當前最優解的概率大,而當靠近答案時跳出正確答案的可能性又逐漸減小。如有不懂請挪步模擬退火詳解
·偏移過程
這就是上述問題的用武之地了:以一定的概率不選當前最優解中的那個物品,從而衍生出另一種方案,如果比剛剛的更好,那麽說明運氣很好,跳到了一個更優解範圍附近
1 if(accept(dE)) 2 {//以上述概率發生轉移 3 if(vis[a]) 4 { 5 vis[a] = false; 6 tot -= v[a]; 7 }//在當前物品已選的情況下放棄選用當前物品 8 else 9 { 10 if(tot + v[a] > V) 11 { 12 continue; 13 } 14 vis[a] = true; 15 tot += v[a]; 16 }//在當前物品未選的情況下嘗試選用當前物品 17 }
·退火步驟
while(T > 1e-14) { ans=max(ans,tot); //維護最優答案,以防非酋情況發生 a = rd; //進行隨機 int dE = v[a]; if(vis[a]) { dE *= -1; //產生能量差 } if(accept(dE)) {//發生轉移 if(vis[a]) { vis[a] = false; tot -= v[a]; } else { if(tot + v[a] > V) { continue; } vis[a] = true; tot += v[a]; } } T *= delta; //降溫 }
該過程通過降溫系數delta對初溫為T的物體降溫,直到物體溫度冷卻接近0。但是不能直接將tot作為答案輸出,否則沒洗臉的話可能會出現跳到了較劣解的情況。
退火的一些小技巧
1. 降溫系數用0.99789(玄學參數)
2. 初溫設置為1926(玄學參數)
3. 退火的轉移概率計算式:e^(-dE/kT)
(del>0)||exp(-del/T) > (double)rand()/RAND_MAX
4.最低溫不要調的太低,不然妥妥的TLE
5.交一次不行說明rp不夠你的時間不好,原代碼再交一次也許 就行了呢
6.別忘了洗臉rp++
番外篇:論歐皇的養成
iewqufhiwefdiweduiqwediuqedwedjewui
(被某個非酋網友摁在鍵盤上打/笑哭)
這是某個沒洗臉的基佬的↑
這是我的↓
溜了溜了……
[蒟蒻實驗室]Ep.1背包退火!