01分数规划

dalao的blog原址

题外话:
写题的时候遇到了这个算法,xue微了解一下吧

0/1分数规划

根据楼教主的回忆录,他曾经在2005年的ACM地区赛赛场上秒掉了一道最优比率生成树问题,导致很多人跟风失败
(瑟瑟发抖。。。)

问题描述

给定两个数组, a[i] a [ i ] 表示选取 i i 的收益,b[i]表示选取 i i 的代价
如果选取i,定义x[i]=1否则 x[i]=0 x [ i ] = 0
每一个物品只有选或者不选两种方案,求一个选择方案
使得 R=a[i]x[i]b[i]x[i] R = ∑ a [ i ] ∗ x [ i ] ∑ b [ i ] ∗ x [ i ] 取得最值
即所有选择物品的总收益/总代价的值最大或是最小

01分数规划问题主要包含一般的01分数规划,最优比率生成树问题,最优比率环问题等
我们将会对这三个问题进行讨论

本文主要讨论最大值的情况

首先我们需要好好的端详一下目标式:

R=a[i]x[i]b[i]x[i] R = ∑ a [ i ] ∗ x [ i ] ∑ b [ i ] ∗ x [ i ]

定义一个函数 F(L)=a[i]x[i]Lb[i]x[i] F ( L ) = ∑ a [ i ] ∗ x [ i ] − L ∗ ∑ b [ i ] ∗ x [ i ]
显然这只是对目标式的一个简单的变形

分离参数,得到 F(L):=(a[i]Lb[i])x[i] F ( L ) := ∑ ( a [ i ] − L ∗ b [ i ] ) ∗ x [ i ]
这时我们就会发现,如果L已知的话, a[i]Lb[i] a [ i ] − L ∗ b [ i ] 就是已知的
d[i]=a[i]Lb[i] d [ i ] = a [ i ] − L ∗ b [ i ] ,那么 F(L):=d[i]x[i] F ( L ) := ∑ d [ i ] ∗ x [ i ]

实际上,L就是目标式中的R,最大化R也就是最大化L

F的值是由两个变量共同决定的,即方案X和参数L
对于一个确定的参数L来说,方案的不同会导致对应的F值的不同,那么这些东西对我们有什么用呢?

假设我们已知在存在一个方案X使得 F(L)>0 F ( L ) > 0 ,这能够证明什么?

F(L)=a[i]x[i]Lb[i]x[i]>0 F ( L ) = ∑ a [ i ] ∗ x [ i ] − L ∗ ∑ b [ i ] ∗ x [ i ] > 0 a[i]x[i]b[i]x[i]>L ∑ a [ i ] ∗ x [ i ] ∑ b [ i ] ∗ x [ i ] > L
也就是说,如果一个方案使得 F(L)>0 F ( L ) > 0 ,说明存在更优的一个L

显然,d数组是随着L的增大而单调减的
也就是说,存在一个临界的L使得不存在一种方案,能够使 F(L)>0 F ( L ) > 0 .
我们猜想,这个时候的L就是我们要求的最优解
之后更大的L值则会造成无论任何一种方案,都会使 F(L)<0 F ( L ) < 0
类似于上面的那个变形,我们知道, F(L)<0 F ( L ) < 0 是没有意义的,因为这时候的L是不能够被取得的
F(L)=0 F ( L ) = 0 时,对应方案的R值恰好等于此时的L值

千万不要把F值同R值混淆
F值是根据我们的变形式求的d数组来计算的,而R值则是我们所需要的真实值,他的计算是有目标式决定的
F值只是提供了一个证据,告诉我们真正最优的R值在哪里,与R值本身并没有什么必然的联系

根据这样的一段性质,很自然的就可以想到二分L值
验证是否存在一组解使得 F(L)>0 F ( L ) > 0 ,有则移动下界,没有则移动上界

所有的01分数规划都是这种思路,唯一的区别就在于求解时的不同——因为每一道题的限制条件不同,并不是每一个解都是可行解的
比如在普通的数组中,你可以选取1,2,3号元素
但在生成树问题中,若1,2,3号元素恰好构成了一个环,那就不能够同时选择了
具体问题,具体分析

二分是一个非常通用的办法
但是我们来考虑这样的一个问题:二分的时候我们只是用到了 F(L)>0 F ( L ) > 0 这个条件,而对于使得 F(L)>0 F ( L ) > 0 的这组解所求到的R值没有使用
因为 F(L)>0 F ( L ) > 0 ,我们已经知道了R是一个更优的解,与其漫无目的的二分,为什么不将解移动到R上去呢?

求01分数规划的另一个方法:Dinkelbach
就是基于这样的一个思想
我们并不去二分答案,而是先随便给定一个答案
然后根据更优的解不断移动答案,逼近最优解
由于ta对每次判定使用的更加充分,所以比二分会快很多
但是,ta的弊端就是需要保存这个解,而我们知道,有时候验证一个解和求得一个解的复杂度是不同的
二分和算法写法都非常简单,各有长处,大家要根据题目谨慎使用

伪代码
//--------------------二分法---------------------

L=...; R=...;

do
{
    mid=(L+R)/2;

    for (int i=1;i<=X;i++) 
        D[i]=A[i]-mid*B[i];

    if 检查(X) 成功
        L=mid;
    else R=mid; 
}
while (abs(L-R)<eps);

//--------------------Dinkelbach---------------------

L=你随意;

do
{
    ans=L;

    for (int i=1;i<=X;i++)
        D[i]=A[i]-L*B[i];

    p=0; q=0;

    for (i=每一个元素)
        如果元素i在解中
            p+=A[i],
            q+=B[i];

    L=p/q; 
}
while (abs(ans-L)<eps);
例题

最优比率生成树问题

问题描述

有带权图G, 对于图中每条边 e[i] e [ i ] , 都有 benifit[i] b e n i f i t [ i ] (收入)和 cost[i] c o s t [ i ] (花费), 我们要求的是一棵生成树 T T , 它使得benifit[i]cost[i],iT最大(或最小).

01分数规划

x[i] x [ i ] 等于1或0, 表示边 e[i] e [ i ] 是否属于生成树.

则我们所求的比率: R=benifit[i]x[i]cost[i]x[i],0i<m R = ∑ b e n i f i t [ i ] ∗ x [ i ] ∑ c o s t [ i ] ∗ x [ i ] , 0 ≤ i < m

设函数 F(L)=benifit[i]x[i]Lcost[i]x[i] F ( L ) = ∑ b e n i f i t [ i ] ∗ x [ i ] − L ∗ ∑ c o s t [ i ] ∗ x [ i ]
F(L)=(benifit[i]Lcost[i])x[i] F ( L ) = ∑ ( b e n i f i t [ i ] − L ∗ c o s t [ i ] ) ∗ x [ i ]
d[i]=benifit[i]Lcost[i] d [ i ] = b e n i f i t [ i ] − L ∗ c o s t [ i ]
我们可以兴高采烈地把 F(L) F ( L ) 看做以 d d 为边权的最大生成树

明确两个性质

  • F(L)单调递减
    证明:因为 cost c o s t 为正数, 所以 F F L的减小而增大.

    • F(max(R))=0 F ( m a x ( R ) ) = 0
      证明:若 F(max(R))<0,benifit[i]x[i]max(R)cost[i]x[i]<0 F ( m a x ( R ) ) < 0 , ∑ b e n i f i t [ i ] ∗ x [ i ] − m a x ( R ) ∗ ∑ c o s t [ i ] ∗ x [ i ] < 0 , 可化为 max(R)<max(R) m a x ( R ) < m a x ( R ) ,矛盾;
      F(max(R))>=0 F ( m a x ( R ) ) >= 0 , 根据性质1, 当 F(R)=0 F ( R ) = 0 R R 最大.

    复杂度:
    时间:O(O(MST)logmax(R))
    空间: O(O(MST)) O ( O ( M S T ) )

    一般的,我们在求MST的时候,Kruskal和Prim都可
    不过尽量不要在稠密图上使用Kruskal

    例题

    最优比率环问题

    问题描述

    求一个环的 {点权和} 除以 {边权和} ,使得那个环在所有环中 {点权和} 除以 {边权和} 最大

    v[i]e[i] ∑ v [ i ] ∑ e [ i ]
    其中v是环中点的价值,e是环中边的价值

    设答案为 ans a n s
    则对于所有环都有: v[i]e[i]<=ans ∑ v [ i ] ∑ e [ i ] <= a n s
    anse[i]v[i]>=0 a n s ∗ ∑ e [ i ] − ∑ v [ i ] >= 0
    对于答案 k k
    k<ans时,就存在至少一个环 ke[i]v[i]<0 k ∗ ∑ e [ i ] − ∑ v [ i ] < 0 ,即有负权回路(边权为 ke[i]v[i] k ∗ e [ i ] − v [ i ]
    k>=ans k >= a n s 时,就对于所有的环 ke[i]v[i]>=0 k ∗ ∑ e [ i ] − ∑ v [ i ] >= 0 ,即没有负权回路

    二分答案,将新的边权设为 ke[i]v[i] k ∗ e [ i ] − v [ i ] ,用 spfa s p f a 来判断负权回路即可

    例题
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值