zoukankan      html  css  js  c++  java
  • 0-1分数规划

    定义

    我们给定两个数组,(a_i)表示选取(i)的收益,(b_i)表示选取(i)的代价。

    如果选取(i),定义(x_i=1)否则(x_i=0),每个物品只有选和不选的两种方案,求一个选择的方案使得

    [max{frac{sumlimits_{i=1}^{n}a_ix_i}{sumlimits_{i=1}^{n}b_ix_i}} ]

    也就是选择物品的总收益/总代价最大或者最小。

    主要问题分类

    一般0-1分数规划

    洛谷P1570 KC喝咖啡
    题目概述:有(n)杯种调料,每种调料有美味值(a_i)和时间(b_i),从中选择(m)种使得

    [max{frac{sumlimits_{i=1}^{n}a_ix_i}{sumlimits_{i=1}^{n}b_ix_i}} ]

    其实就是板子啦

    我们来考虑一下这个问题:

    贪心?我不会

    (dp)?,我也不会

    我们设设答案为(t),则(tlefrac{sumlimits_{i=1}^{n}a_ix_i}{sumlimits_{i=1}^{n}b_ix_i})

    将分母移项,得到(sumlimits_{i=1}^{n}a_ix_ige t*sumlimits_{i=1}^{n}b_ix_i)

    再把代数式移到一侧(sumlimits_{i=1}^{n}a_ix_i-t*sumlimits_{i=1}^{n}b_ix_ige 0)

    我们把(sum)合并,再把(x_i)提出来得到(sumlimits_{i=1}^{n}x_i(a_i-t*b_i)ge 0)

    我们发现,如果要尽量满足(sumlimits_{i=1}^{n}x_i(a_i-t*b_i)ge 0),那么只需要取出前(m)大的(a_i-t*b_i)就可以了

    我们设(f(t)=sumlimits_{i=1}^{n}x_i(a_i-t*b_i)),会发现其实它是一个关于(t)的单调函数,那么我们岂不是可以二分(t)然后再(check)一下

    等等,那这不就是二分答案吗?

    没错,(0)-(1)分数规划就是变形一下式子再二分答案(qwq)

    洛谷P4377 [USACO18OPEN]Talent Show

    题目概述:不要求选(m)种,但是每个物品有一个(w_i),要求选择的物品(w_i)之和大于(m),求

    [max{frac{sumlimits_{i=1}^{n}a_ix_i}{sumlimits_{i=1}^{n}b_ix_i}} ]

    变形之后没什么不同的,但是由于有一个所选物品(w_i)之和大于(m)的限制,所以我们不采用贪心,而采用背包的方法进行(check)

    洛谷P2115 [USACO14MAR]破坏Sabotage

    题目概述:一个数列,选择其中一段连续期间去掉(规定头和尾不能去掉),求剩下数字平均值的最小值;

    关于区间和问题我们很容易联想到前缀和,设(s_i)为数列的前缀和数组

    则方程可以列为(t=frac{s_n-(s_r-s_{l-1})}{n-(r-l+1)})

    变变变得到(s_n-t*n-(s(r)-t*r)+s(l-1)-t*(l-1)ge 0)

    很多变量很难处理,我们设(g_x=s_x-t*x),则(g_n-g_r+g_{l-1}ge 0)

    考虑如何(check)

    我们发现,该题目中最小值存在实际意义,即在某个较小区间内是不含有答案的,但是二分边界可以无限缩小

    所以我们转变思路:由于(t)是最小值,如果对于一个(t),我们能找到一个(g_r-g_{l-1}>g_n),那么这个(t)就凉了

    我们可以求一个(maxn_i)表示(g_i)前缀最大值,(minn_i)表示(g_i)后缀最小值,枚举每个(i)判断(maxn_i-minn_i)是否大于(g_n)

    这个东西是单调的,用这种方法只要找(t)的最大值就好了,这个东西它的边界是不用特殊处理的,可以很愉快的二分(check)啦~

    代码什么的我才懒得放,自己脑补不出来也敢说自己学会了

    最优比率生成树

    应用:选择(n-1)条边使图变成完全图,求点权与边权比值的最大(小)值

    洛谷P4951 [USACO 2001 OPEN]地震

    题目概述:有一只施工队要修路,每条路有成本(c)和需要的时间(t),总收入为(k),要求选择数条边使图联通,求

    [max{frac{k-sumlimits_{i=1}^{n}c_ix_i}{sumlimits_{i=1}^{n}t_ix_i}} ]

    然后怎么办?按照套路设式子呗

    (ansle frac{k-sumlimits_{i=1}^{n}c_ix_i}{sumlimits_{i=1}^{n}t_ix_i})

    移项(ans*sumlimits_{i=1}^{n}t_ix_i+sumlimits_{i=1}^{n}c_ix_i-kle 0)

    整理(sumlimits_{i=1}^{n}x_i*(ans*t_i-c_i)-kle 0)

    我们二分一个(ans),以(ans*t_i-c_i)为边权,跑最小生成树,判断原式是否小于等于(0)

    最优比率环

    应用:在有向图中找到一个环使得环内的点权与边权比值最大(最小)
    洛谷P2868 [USACO07DEC]观光奶牛Sightseeing Cows

    题目概述:每个点有点权,每条边有边权,求一个环,使得环内(max{frac{sumlimits_{vin V}v_i}{sumlimits_{ein E}e_i}}),求这个最大值

    求这个最大值

    设每个点点权为(v_i),每条边边权为(e_i)

    假设一个环内的(tle frac{sumlimits_{vin V}v_i}{sumlimits_{ein E}e_i}),问题即为求(t)的最大值,可以拓展为(01)分数规划问题

    套路移项得到(sumlimits_{vin V}v_i-t*sumlimits_{ein E}e_ige 0)

    设当前环为(g)

    再合并(sumlimits_{u,vin g,u,vin E}v_i-t*e_ige 0)

    我们以(v_i-t*e_i)为边权,只要某个环上的边权和为正就满足要求,所以就变成了一个判正环的问题,当然也可以取反判负环

    注意这个(v_i)只要在入点和出点之中选一个就好了,但是要统一

    现在我们就可以写一个广为人知的最短路算法了(雾

    可以发现(01)分数规划本质就是列个不等式然后在实数域上二分,算是稍微加一点数学知识的二分答案吧

  • 相关阅读:
    CCF-CSP认证 C++题解目录
    LeetCode周赛#205
    LeetCode双周赛#34
    Codeforces Round #667 (Div. 3) B、C、D、E 题解
    Codeforces Round #656 (Div. 3) 题解
    牛客小白月赛#26 题解
    LeetCode周赛#204 题解
    LeetCode周赛#203 题解
    牛客小白月赛#27 题解
    N阶上楼梯问题——动态规划(递推求解)
  • 原文地址:https://www.cnblogs.com/knife-rose/p/12031782.html
Copyright © 2011-2022 走看看