分数规划小结

这篇博客总结了分数规划的算法分析和典型例题,包括最优比率生成环、最优比率生成树、树形背包01分数规划和最大流分数规划。通过二分法解决这些问题,构建新的图并判断是否存在满足条件的结构。
摘要由CSDN通过智能技术生成

分数规划

1.算法分析

01分数规划是这样的一类问题,有一堆物品,每一个物品有一个收益 a i ai ai,一个代价 b i bi bi,我们要求一个方案,选出k个物品,使选择的 ∑ a i / ∑ b i \sum{ai}/\sum{bi} ai/bi最大。

基本做法是采用二分法,假设当前二分到的答案为x,那么:

∑ a i / ∑ b i > = x \sum{ai}/\sum{bi}>=x ai/bi>=x可以转化为: ∑ ( a i − x ∗ b i ) > = 0 \sum{(ai-x*b_i)}>=0 (aixbi)>=0,所以每次check的时候将 a i − x ∗ b i a_i-x*b_i aixbi进行排序,取前k个,判断他们的和是否大于等于0即可

2.模板

/*poj2976:给出两个数组a和b,$a_i$代表这门课获得的成绩,$b_i$代表这门课的满分是多少,现在要求你舍弃掉k门课,使得平均绩点($100*\sum{ai}/\sum{bi}$)最高。直接二分即可,注意是舍弃k门课,所以相当于选择n-k门课,另外输出需要四舍五入,可以直接利用.0lf进行四舍五入*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <algorithm>
#include <iostream>
#include <limits>
#include <map>
#include <set>
#include <vector>

using namespace std;

const int N = 1e6 + 5;
typedef long long LL;
int k, n;
double a[N], b[N], c[N];

const double eps = 1e-8;
// 和0做比较
int sgn(double x) {
   
    if (fabs(x) < eps) return 0;  // =0
    if (x < 0)
        return -1;  // < 0
    else
        return 1;  // > 0
}

bool check(double mid) {
   
    for (int i = 0; i < n; i++) c[i] = a[i] - mid * b[i];
    sort(c, c + n);
    double sum = 0;
    for (int i = n - 1; i >= k; i--) sum += c[i];  //选n-k项
    return (sgn(sum) >= 0);
}

int main() {
   
    while (scanf("%d%d",&n,&k)) {
   
        if ((n + k) == 0) break;
        for (int i = 0; i < n; i++) scanf("%lf", &a[i]);
        for (int i = 0; i < n; i++) scanf("%lf", &b[i]);
        double l = 0, r = 1;           //成绩最大是1,也就是满分
        while (r - l > 1e-8) {
            // r与l的间隔小于1e-8
            double mid = (l + r) / 2;  // 不需要考虑加一的事情
            if (check(mid))
                l = mid;
            else
                r = mid;  // r和l都是mid}
        }
        printf("%.0lf\n",l*100);//四舍五入
    }
    return 0;
}

3.典型例题

3.1 最优比率生成环

acwing361观光奶牛
题意: 给定一张L个点、P条边的有向图,每个点都有一个权值f[i],每条边都有一个权值t[i]。求图中的一个环,使“环上各点的权值之和”除以“环上各边的权值之和”最大。输出这个最大值。 点数N~1e3, 边数M~5e3
题解: 二分枚举答案,然后根据这个mid来重新构图,与 a i − m i d ∗ b i a_i-mid*b_i aimidbi类似,本题为$ f[t]-midw[i] 的 和 是 否 大 于 0 , 那 么 将 每 个 点 的 权 值 下 放 到 边 上 , 然 后 判 断 是 否 存 在 正 环 即 可 , 也 可 以 变 个 符 号 , 判 断 是 否 存

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值