Loading [MathJax]/extensions/TeX/newcommand.js
\newcommand{\ord}[1]{\mathcal{O}\left(#1\right)} \newcommand{\abs}[1]{\lvert #1 \rvert} \newcommand{\floor}[1]{\lfloor #1 \rfloor} \newcommand{\ceil}[1]{\lceil #1 \rceil} \newcommand{\opord}{\operatorname{\mathcal{O}}} \newcommand{\argmax}{\operatorname{arg\,max}} \newcommand{\str}[1]{\texttt{"#1"}}

2016年12月7日 星期三

[ 0-1 Fractional Programming Dinkelbach algorithm ] 0-1分數規劃

【定義】

給你兩個數組,benefit[i]表示選i的利潤、cost[i]表示選i的花費。
如果選i,定義x[i]=1否則x[i]=0,通常題目會給你選擇的限制條件,像是必須是一顆生成樹之類的,這裡就把它忽略掉
我們的目標是要求\frac{\sum{benefit[i] \times x[i]}}{\sum{cost[i] \times x[i]}}的最大值。

【分析】

先不管最大化問題,令\frac{\sum{benefit[i] \times x[i]}}{\sum{cost[i] \times x[i]}}=L
可以把式子改寫成(\sum{benefit[i] \times x[i]})-L \times (\sum{cost[i] \times x[i]})=0
分離參數得到\sum{(benefit[i]-L \times  cost[i]) \times x[i]}=0
只要知道L(benefit[i]-L \times  cost[i])是直接可以求出來的,先記他為d(i,L)
那可以設f(L)=\sum{d(i,L) \times x[i]}

我們的目標變成是要最大化L
那若存在一種x的選法使得f(L)>0能夠證明什麼呢?
f(L)>0 \to \frac{\sum{benefit[i] \times x[i]}}{\sum{cost[i] \times x[i]}}>L那表示存在另一個L會比現在的L還要好
f(L)<0?很明顯這種情況完全沒有意義,因為找不到這種L

最佳的L會讓所有x的選法都f(L)\leq0,只要找到這樣的L就說明他是最佳解了
也可以用類似的想法求最小化L,這裡就不贅述了。

【解法】

根據剛剛找出來的性質f(L)是單調性的,我們可以二分搜L,然後驗證是否存在一組解使得f(L)>0,這很簡單就不附code了。
另一個有效率的算法是Dinkelbach,他跟二分搜不一樣的地方是他要去求解,在驗證解跟求解的複雜度一樣的時候Dinkelbach是會比較快的,但有時候求解的複雜度會比驗證解的複雜度還要高,因此要看情況使用
以下附上虛擬碼:
Dinkelbach(){
L=任意狀態(通常設為0);
do{
Ans=L;
for(i:所有元素)d[i]=benefit[i]-L*cost[i];//計算d值
找出一組使f(L)最大的x;
p=0,q=0;
for(i:所有元素){
if(x[i])p+=benefit[i],q+=cost[i];
}
L=p/q;//更新解,注意q=0的情況
}while(abs(Ans-L)>EPS);
return Ans;
}
view raw Dinkelbach.cpp hosted with ❤ by GitHub

常見的題型有:最優比率環、最優比率生成樹、最大密度子圖(有flow解)等

2 則留言: