01分數(shù)規(guī)劃算法 信息學(xué)競賽 OI ACM 二分 Dinkelbach 最優(yōu)比率生成樹 最優(yōu)比率環(huán)
01分數(shù)規(guī)劃
張?zhí)煜?/font>
blog.csdn.net/hzoi_ztxztx97@QQ.com
前置技能
二分思想最短路算法一些數(shù)學(xué)腦細胞?
問題模型1
基本01分數(shù)規(guī)劃問題
給定n個二元組(valuei,costi),valuei是選擇此二元組獲得的價值(非負),costi是選擇此二元組付出的代價(非負),設(shè)xi(xi∈{0,1})代表第i個二元組的選與不選,最大(小)化下式 maximize(or minimize) r=∑valuei?xi∑costi?xi
解決方法
二分法
設(shè)r最大值為r?, r?=∑valuei?xi∑costi?xi
∑valuei?xi?r??∑costi?xi=0
設(shè)一個函數(shù),自變量為r值, f(r)=∑valuei?xi?r??∑costi?xi
觀察這個函數(shù),假如{xi}固定,則這個函數(shù)就是坐標系中一條直線(y=B?A?x),每一組{xi}對應(yīng)著一條直線,這些直線斜率非正(因為?A=?∑costi?xi≤0),縱截距非負(因為B=∑valuei?xi≥0 ),如圖1。
對于每一條直線,當f(r)=0時,橫截距就是這一組的r,那么r?就是每條直線橫截距的最大值(每組{xi}對應(yīng)r的最大值)如圖2。
在圖中上任取一條垂直x軸的豎線, 如果存在直線與這條豎線的交點縱坐標為正,那么最優(yōu)值一定在當前豎線的右側(cè); 如果所有直線與這條豎線交點縱坐標為負,那么最優(yōu)值一定在當前豎線的左側(cè); 如果所有直線與這條豎線交點縱坐標非正且存在直線與這條豎線交點縱坐標為0,那么當前豎線橫坐標即為最優(yōu)值r?。
按照這個思想,可以二分答案r,那么二分時如何進行判斷呢?
選擇一個r時需要判斷所有f(r)的最大值是否為0,如果max{f(r)}>0則r<r?;如果max{f(r)}<0 則 r>r?。 怎樣求max{f(r)}? f(r)=∑valuei?xi?r?∑costi?xi=∑(valuei?r?costi)?xi
二分一個r時,每個二元組的valuei?r?costi 都可以求出,設(shè)其為weighti,現(xiàn)在的目標就是找到一組{xi}使得∑wighti?xi最大(即求max{f(r)})。怎么找到這一組{xi},或者直接求得max{f(r)}呢?具體問題具體分析,經(jīng)常借助最短路算法判斷是否存在負環(huán)。下面會有幾道例題。
01分數(shù)規(guī)劃還會與其他問題結(jié)合,如網(wǎng)絡(luò)流等。
Dinkelbach算法
這個算法我是在寫這篇文章時才知道的。
思考上述二分算法的思路,設(shè)二分過程中某一個二分值為r,二分時的判斷條件是max{f(r)}的正負性,而這個r除了讓L右移或者R左移就沒有用了。現(xiàn)在思考某一過程中r與max{f(r)}能否再被利用。 二分時,假如max{f(r)}>0這說明最優(yōu)解在當前r的右側(cè),于是讓L=r,但是,如果將L移動到max{f(r)}對應(yīng)直線的橫截距呢?顯然,算法會變得更快。這個思想就是Dinkelbach算法的內(nèi)涵。 Dinkelbach實質(zhì)上是一種迭代算法,基于這樣的思想:不去二分答案,而是先隨便給定一個答案,然后根據(jù)更優(yōu)的解(max{f(r)}對應(yīng)直線的橫截距)不斷移動答案,逼近最優(yōu)解。理論上它比二分快些。 在這個算法中,一般將r初始化為0。
兩種算法的比較
Dinkelbach算法的弊端就是需要保存解。這兩個算法解決統(tǒng)一問題實際上都有可能快些。 我覺著我一般還是用二分。。。。
例題
只先寫了文章,還差相關(guān)題目的分析,代碼等。得等個一兩天再。2017-02-06留。
Poj2976Dropping tests
問題模型2
最優(yōu)比率生成樹
帶權(quán)無向圖G, 對于圖中每條邊ei, 都有valuei和costi,現(xiàn)在求一棵生成樹T,最大(小)化∑valuei∑costi,ei∈T
解決方法
套用01分數(shù)規(guī)劃模型,如果ei∈T則xi=1否則xi=0。
二分法
二分答案r,邊賦值weighti=valuei?r?costi,因為是生成樹,邊的數(shù)量確定,那么max{f(r)}需要選取前|G|?1大的weighti,也就是求最大生成樹,按最大生成樹權(quán)值的正負性就可以二分了。
Dinkelbach算法
當前答案r,邊賦值weighti=valuei?r?costi,同樣求最大生成樹,找到max{f(r)}對應(yīng)的邊集{xi},也就是最大生成樹的邊集。對這個邊集找橫截距當做下一次答案。橫截距是啥呢? f(r)=B?A?rrr=0=B/A=∑valuei?xi∑costi?xi
例題
poj2728Desert King(最優(yōu)比率生成樹)
問題模型3
最優(yōu)比率環(huán)
給定有點權(quán)和邊權(quán)的圖,求一個環(huán),使得環(huán)的點權(quán)和與邊權(quán)和的比值最大。
解決方法
套用01分數(shù)規(guī)劃模型,點權(quán)為valuei,邊權(quán)為costi,一個環(huán)為C 問題要求最大化∑valuei∑costi,(i∈C) 邊數(shù)和點數(shù)是相同的,但上述式子表述不是很正確,意會即可。 若答案為r?,那么任意一個環(huán) ∑valuei∑costi∑valueir??∑costi?∑valuei≤r?≤r??∑costi≥0
二分法
設(shè)當前答案r, r<r?,至少存在一個環(huán),r?∑costi?∑valuei<0,即存在負權(quán)回路(將邊權(quán)設(shè)為r?costi?valuei,不是提前算出,而是在更新路徑的時候從哪個點訪問到這條邊的就將這條邊設(shè)為相應(yīng)點權(quán)與邊權(quán)的對應(yīng)值); r≥r?,則不存在負環(huán)。
求負環(huán)可以用Bellman-Ford,但是比較慢,一般用spfa算法求負環(huán) 具體判斷方法為,一個點不能入隊n次,否則有負環(huán);一條最短路徑長度不能到n,否則有負環(huán)。兩個判斷方法可以同時使用。
Dinkelbach算法
如果用這個算法需要記錄下來一個負環(huán),實現(xiàn)還是能實現(xiàn)的,但是沒有二分+spfa好寫。
例題
poj 3621(最優(yōu)比率環(huán))
問題模型4
最大密度子圖
這個問題會寫在網(wǎng)絡(luò)流總結(jié)中。
參考資料
【1】KirisameMarisa - NYIST 914Yougth的最大化【二分搜索/Dinkelbach算法】 【2】PerSeAwe - [Algorithm]01分數(shù)規(guī)劃