【总结】01分数规划
定义
我们给定两个数组,\(a_i\) 表示 \(i\) 的价值,\(b_i\)表示选取 \(i\) 的代价。如果选取 \(i\),定义 \(x_i = 1\) 否则 \(x_i = 0\)。每个物品只有选和不选的两种方案,求一个选择的方案使得 \(R = \frac{\sum (a_i \cdot x_i)}{\sum(b_i \cdot x_i)}\),也就是选择物品的总收益除以总代价最大或者最小。
01分数规划问题主要包含以下几个问题:
- 一般的01分数规划
- 最优比率生成树
- 最优比率环
01分数规划
\(F(L) = \sum(a_i \cdot x_i) - L \cdot \sum(b_i \cdot x_i)\)
可以化简得到
\(F(L) = \sum(x_i \cdot (a_i - L \cdot b_i))\)
再用 \(d_i\) 替代 \(a_i - L \cdot b_i\)
又可以得到 \(F(L) = \sum(x_i \cdot d_i)\)
而我们的最优解 \(R\), 就可以通过二分得到
例题
01 分数规划
这是一道板子题
我们之前已经得到了
\[F(L) = \sum(x_i \cdot (a_i - L \cdot b_i))
\]
我们可以二分答案,二分出的 \(mid\) 就是函数中的 \(L\), 我们就可以得到 \(d_i\), 由于恰好有 \(K\) 个 \(x_i\) 为 \(1\),由于我们要让 \(F(L) \geq 0\) 所以我们取 \(d_i\) 的前 \(k\) 大的值。
核心代码如下
bool cmp(double x, double y) {
    return x > y;
}
bool check(double m) {
    for (int i = 1; i <= n; i++)
        d[i] = 1.0 * a[i] - m * b[i];
    sort(d + 1, d + n + 1, cmp);
    double sum = 0;
    for (int i = 1; i <= k; i++)
        sum += d[i];
    return sum >= 0; 
}
while (r - l >= eps) {
double mid = (l + r) / 2;
    if (check(mid))
        l = mid;
    else
        r = mid;
}
背包问题 V3
本文来自博客园,作者:zhou_ziyi,转载请注明原文链接:https://www.cnblogs.com/zhouziyi/p/16518949.html

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号