0-1分数规划问题

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对于分数规划的算法。Dinkelbach算法产生了收敛于L*的参量序列,如图1中细线所示的方式。这里我们记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个元素,使得0-1分数规划问题_第1张图片最大。

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.最大密度子图

详见《最大权闭合图&&最大密度子图》


你可能感兴趣的:(c,算法,search,ini)