最优比率树(转)
转自:http://blog.163.com/silver9886@126/blog/static/35971862201493144512351/ (silver9886@126的博客)
题意:
给定n个二元组(a,b),删除k个二元组,使得剩下的a元素之和与b元素之和的比率最大(比率最后乘100输出)
题解:
最裸的01分数规划,以此题为例讲述如何构造。
同意的题目:
n a certain course, you take n tests. If you get ai out of bi questions correct on test i, your cumulative average is defined to be
.
Given your test scores and a positive integer k, determine how high you can make your cumulative average if you are allowed to drop any k of your test scores.
那我们来看下解法:
概念
有带权图G, 对于图中每条边e[i], 都有benifit[i](收入)和cost[i](花费), 我们要求的是一棵生成树T, 它使得 ∑(benifit[i]) / ∑(cost[i]), i∈T最大(或最小).
这显然是一个具有现实意义的问题.
解法之一 0-1分数规划
设x[i]等于1或0, 表示边e[i]是否属于生成树.
则我们所求的比率 r = ∑(benifit[i] * x[i]) / ∑(cost[i] * x[i]), 0≤i<m.
为了使 r 最大, 设计一个子问题---> 让 z = ∑(benifit[i] * x[i]) - l * ∑(cost[i] * x[i]) = ∑(d[i] * x[i])最大 (d[i] = benifit[i] - l * cost[i]) , 并记为z(l). 我们可以兴高采烈地把z(l)看做以d为边权的最大生成树的总权值.
然后明确两个性质:
1. z单调递减
证明: 因为cost为正数, 所以z随l的减小而增大.
2. z( max(r) ) = 0
证明: 若z( max(r) ) < 0, ∑(benifit[i] * x[i]) - max(r) * ∑(cost[i] * x[i]) < 0, 可化为 max(r) < max(r). 矛盾;[这里解释一下,假设我们将benifit[i]和x[i],cost[i]都取r=max(r)时候的值,我们就可以得到max(r)>max(r)的荒谬结论 ]
若z( max(r) ) >= 0, 根据性质1, 当z = 0 时r最大. {解释一下,可以推导得到max(r)<=∑(benifit[i] * x[i]) / ∑(cost[i] * x[i]),那么当然取z( max(r) ) = 0时,max(r)的值为最大}
到了这个地步, 七窍全已打通, 喜欢二分的上二分, 喜欢Dinkelbach的就Dinkelbach.
具体代码后续研究
今天具体研究了下二分法的代码。试图解释最优比例生成树。
首先我们明白这样一个道理:
1.z = ∑(benifit[i] * x[i]) - l * ∑(cost[i] * x[i]) = ∑(d[i] * x[i]),如果l是最大值的话,那么任意的benifit[i]和cost[i] 的组合都是使得z<=0的,如果I不是最大值,一定有这样的benifit[i]和cost[i]使得z>0.
好了我们知道l>0,则无论 ∑(benifit[i] * x[i])和∑(cost[i] * x[i])取何值(注意,根据题意这两个数必定是正数),z的函数一定是通过二,四象限的直线方程。则我们作图如下: