0-1分数规划问题

【问题定义】

求出解集{xi|xi=01}使目标(c1x1+c2x2+...+cnxn)/(d1x1+d2x2+…+dnxn)=cx/dx达到最大。 

【解题思路】

对于分数规划问题,许多算法都能利用下面的线性目标函数解决问题。
    Q(L): 最小化cx-Ldx,xi∈{0,1}
    记z(L)为Q(L)的最值。令x*为分数规划的最优解,并且令L*= (cx*)/(dx*),即分数规划的最值。
    那么:z(L) > 0   当且仅当   L<L*
               z(L) = 0   当且仅当   L=L*
               z(L) < 0   当且仅当   L>L*
因此,解决分数规划问题在本质上等同于寻找L=L*使z(L)=0。出于此目的,关于L的函数z(L)具有很多不错的性质:分段线性,凹函数,严格递减,(-nC)<0,且z(nC)>0。
根据上面的性质,显然当确定参量L,便可以检验最值L*是否大于小于或等于当前的L。二分搜索答案对于浮点误差控制较好,但是效率略低。另一种方法类似于牛顿迭代的Dinkelbach算法,二分搜索方法的收敛速度仅仅是线性的,而Dinkelbach的收敛速度却是超线性的。

Dinkelbach算法

其本质上是观察直线:z=cx’-Ldx’
于函数z(L)在L=L’处相切,这里x’是子问题Q(L’)的最优解。因此,-dx’是z(L)在L’处的斜率。而且很容易看出上面的直线与L轴相交于L=cx’/dx’
Dinkelbach对于分数规划的算法,产生了收敛于L*的参量序列,记C=max{max|ci|,1},显然问题的最优解在区间[-nC,nC]内。

Dinkelbach算法:
步骤1:设L=L1,使 L*<=L1<=nC
步骤2:解决子问题Q(L)并得到最优解x
步骤3:如果z(L)=0,那么输出x并终止;否则,设L=cx/dx跳到步骤2

例:poj3111 K Best

解法:选取k个元素,使得 最大。

double search(double p){  
    for(int i=0;i<n;i++)  
        jw[i].value=jw[i].v-jw[i].w*p;  
	Arrays.sort(jw);  
	double tv=0,tw=0;  
	for(int i=0;i<k;i++){  
        tv+=jw[i].v;  
        tw+=jw[i].w;  	        
    }  
    return tv/tw;  
}  
double ans=1,temp;  
while(true){  
    temp=search(ans);  
    if(Math.abs(ans-temp)<0.001)  
        break;  
    ans=temp;  
}

【0-1分数规划应用】

1.最优比率生成树(poj2526 Desert King)

问题:一个带权完全图,每条边都有自己的花费值cost[i]和 长度dis[i],求一个生成树,使得r=(∑cost[i]*x[i] ) / (∑dis[i]*x[i] )最小。
解法:search时将每条边边权设为cost[i][j]-dis[i][j]*p,求最小生成树时选取的边既为一组解,不断迭代。

2.最优比率环:(poj3621 SightSeeing)

问题:有向图中,每个点有一个权值C(1<=c<=1000),每条边有权值D(1<=D<=1000),要求找出一个环(没有重点),环包含的点数要>=2,使得sum{C}/sum{D}最大。
解法:由于此题求解的是存在性问题,不可套用Dinkelbach算法迭代,因此二分答案求解最大值,对于给定的g如果以<a,b>权重为g*D[b]-C[i]的图中存在环路,则ans>=g(注意二分double时结束条件right-left<eps,转移为left=mid、right=mid)。

3.最大密度子图

猜你喜欢

转载自blog.csdn.net/u013228808/article/details/84948482
今日推荐