zoukankan      html  css  js  c++  java
  • 最优比率树(转)

    转自: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

    最优比例生成树 神题神解法 - silver9886@126 - silver9886@126的博客.

    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]), iT最大(或最小).

    这显然是一个具有现实意义的问题.

    解法之一 0-1分数规划

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

    则我们所求的比率 r = ∑(benifit[i] * x[i]) / ∑(cost[i] * x[i]), 0i<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为正数, 所以zl的减小而增大.

    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的函数一定是通过二,四象限的直线方程。则我们作图如下:

    最优比例生成树 神题神解法 - silver9886@126 - silver9886@126的博客
    z(0)= ∑(benifit[i](求n-k个),则必定z(0)>0,0就是图中的L0点。取z(max(benifit[i]/cost[i])),则必定有z(max(benifit[i]/cost[i]))(求n-k)<0,max(benifit[i]/cost[i])就是图中的L1点。【注意源码中对z值首先进行快排排序的目的就是如果最大的n-kz值和都<0,那么l的这个取值一定对任意的n-k个求和的z值都是<0的,同理,最大值>0一定是在所求点的左方的】而我们的所求点就是上图中的所求点。因此,通过二分法就是求得所求点的有效方法。

     

  • 相关阅读:
    黑马程序员——网络编程
    黑马程序员——File类
    黑马程序员——java IO流
    黑马程序员——java集合框架(Map和工具类)
    黑马程序员——java集合框架之List,Set
    黑马程序员——对线程的一些总结
    黑马程序员——创建线程的两种方式
    java对象的初始化过程
    黑马程序员——java环境变量path和classpath
    JavaScriptoo:以更好的方式选择JS库
  • 原文地址:https://www.cnblogs.com/topW2W/p/5278250.html
Copyright © 2011-2022 走看看