zoukankan      html  css  js  c++  java
  • 分数规划小结

    Preface

    其实分数规划就是化下式子,然后套个二分就没了... 所以分数规划的问题的核心并不在分数规划的部分

    Description

    给你(n)个元素,每一个元素都有两个权值(a_i, b_i),你需要选择若干个元素,最大/小化(frac{sum a_i}{sum b_i})

    Process

    我们可以先二分一个答案每次只需要判断和不合法即可,假设答案为(ans),并且需要最大化分数

    [frac{sum a_i}{sum b_i} geq ans \ sum a_i - ans cdot sum b_i geq 0 \ sum(a_i - ans cdot b_i) geq 0 ]

    这样我们就只需要令一件物品的权值(w_i = a_i - ans cdot b_i),然后判断是否能选出一些物品使得(sum w_i geq 0)即可

    2分钟讲完分数规划

    Problem

    [POJ2976] Dropping tests

    给你(n)个物品,每一个物品都有两个权值(a_i, b_i),你需要选出(k)个物品,最大化

    [100 cdot frac{sum_{i = 1}^{n} a_i}{sum_{i = 1}^{n} b_i} ]

    答案四舍五入至整数

    (n leq 1000, 0 leq k < n)

    Solution

    这就是一道板子题,直接照着前面的方法做

    <p>每次对$w_i$排一遍序,然后取最大的$k$个加起来看是不是大于等于$0$就可以了</p>
    

    [Luogu4322] 最佳团体

    给你一棵树(点编号(0)(n)),每一个节点都有两个属性(p_i, s_i)

    你需要在树上选择(k + 1)个节点,并且选择一个节点的前提选择它的父亲节点(根结点除外),并且最大化(frac{sum p_i}{sum s_i})

    (k leq n leq 2500)

    Solution

    就直接套一个分数规划,然后再做一遍树形依赖背包就可以了

    <p>考虑到可能会有$10^{-10}\%$的人像我一样,可能会不知道树形依赖背包,所以我还是讲一下</p>
    
    <p>我们可以把这棵树转换为$dfn$序,然后就可以在dfn序上$dp$了,设$sz[x]$为以$x$为根的子树的大小</p>
    
    <p>有转移方程
    $$
    	dp[i][j] = max(dp[i + 1][j - 1], dp[i + sz[i]][j])
    $$
    最后答案就是$dp[0][k + 1]$</p>
    
    <p><a href = "https://paste.ubuntu.com/p/Mct5ztjHN5/">Code</a></p>
    

    [Luogu3199] [HNOI2009]最小圈

    给你一个(n)个点(m)条边的带权有向图,你需要找到这个图中最小权值的环

    定义一个环的权值为这个环上所有边边权的平均值

    Solution

    对于这种题目,我们可以对其建模,然后转换为分数规划问题

    <p>我们可以令每一条边有两个边权$a_i, b_i$,其中$a_i$等于边权,$b_i$等于$1$</p>
    
    <p>然后就直接套分数规划,然后判断有没有负环就可以了</p>
    

    [POJ2728] Desert King

    一个国家有(n)座城市,每一个城市都有一个坐标(x_i, y_i)和一个海拔(h_i)

    你需要在城市之间修建恰好(n - 1)条道路,使得所有的城市之间都可以互相到达

    一条道路的长度为两个端点的欧几里得距离,花费为端点的海拔差

    现在你需要修建这些道路,并且要最小化总花费与总长度的比值,输出这个比值

    (n leq 1000)

    Solution

    首先看到比值,就直接转化为分数规划问题

    <p>不难发现,如果直接每次用$kruskal$跑最小生成树显然是会T的,因为可能是完全图</p>
    
    <p>所以我们可以写一个$n^2$的prim来跑 (这东西虽然平时用的不多,但搞稠密图还是有一点用的)</p>
    
    <p><del>另外,本题莫名卡精度</del></p>
    
    <p><a href = "https://paste.ubuntu.com/p/cXTZPzckm4/">Code</a></p>
    

    [Luogu2868] [USA07DEC]观光奶牛

    给你一个有向图,每一个点有一个权值(f_i),每一条边有一个权值(w_i)

    你需要选择一个点,然后以这个点为起点,遍历若干个节点(至少两个)然后回到原点。这时你的快乐值为(frac{sum f_i}{sum w_i})(多次经过一个点只算一次(f_i)(w_i)可以多次计算)

    请问最大的快乐值为多少

    Solution

    我们先套一个分数规划之后,把一条边的权值看成$b_i$,它所指向的点看成$a_i$,不难发现就是要求一个负环

    <p>但是多次经过一个点只会计算一次的限制有怎么处理呢?</p>
    
    <p>我们可以发现如果一个复杂环为负数,那么构成这个复杂环的简单环中至少有一个为负数,所以找到哪个负环都是等价的</p>
    
  • 相关阅读:
    android应用私有存储文件的写入与读取-openFileInput 和 openFileOutput
    android 8种对话框(Dialog)使用方法汇总
    Gradle环境变量的配置
    Activity标题(title)的显示和隐藏
    Android Studio配置Android Annotations框架详解--说说那些坑
    Android如何防止apk程序被反编译
    Android APK反编译 apktool使用教程
    关于Installation error: INSTALL_FAILED_NO_MATCHING_ABIS的解决方法
    Android解决NDK not configured问题
    Android SDK在线更新镜像服务器
  • 原文地址:https://www.cnblogs.com/xunzhen/p/10414817.html
Copyright © 2011-2022 走看看