基本技巧——分数规划 学习笔记

这篇具有很好参考价值的文章主要介绍了基本技巧——分数规划 学习笔记。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

基本技巧——分数规划 学习笔记

引入

分数规划用来求一个分式的极值。

具体的,给定 \(n\) 个元素,每个元素有属性 \(a_i,b_i\),求一个集合 \(P\in[1,n]\),最大/最小化比率:$$\dfrac{\sum_{i\in P}a_i}{\sum_{i\in P}b_i}$$

求解

二分法

假设我们要求最大值(求最小值的方法和求最大值的方法类似),二分一个 \(\text{mid}\),然后推式子(省略范围):

$\begin{array}{ll} &\sum a_i/\sum b_i\ge\text{mid}\\ \Longrightarrow&\sum a_i\ge\sum b_i\times\text{mid}\\ \Longrightarrow&\sum a_i-\sum b_i\times\text{mid}\ge0\\ \Longrightarrow&\sum (a_i-b_i\times\text{mid})\ge0 \end{array}$

\(g(x)=\sum(a_i-b_i\times x)\),则原问题其实就是最大化 \(g(x)\)。可以用二分求解:二分一个 \(\text{mid}\),如果 \(g(\text{mid})\ge0\),则说明可行;否则就是不可行。

实际求解的时候一般是,如果 \(g(\text{mid})>0\),那么就 \(l\leftarrow\text{mid}+1\),否则 \(r\leftarrow\text{mid}\)

在题目中,一般来说,分数规划的难点在于求解 \(g(x)\) 的最大/最小值。

模型

01 分数规划

题目:POJ2976 Dropping tests

题意:在 \(n\) 个物品中选取 \(k\) 个,使得比率最大。

分析:二分最大的比率为 \(\text{mid}\),最大化 \(g(\text{mid})=\sum(a_i-b_i\times\text{mid})\);可以贪心来考虑,将 \(a_i-b_i\times\text{mid}\) 视为物品的权值,将权值前 \(k\) 大的数加起来,即 \(g(\text{mid})\);如果 \(g(\text{mid})>0\),则 \(l\leftarrow\text{mid}+1\),否则 \(r\leftarrow\text{mid}\)

变式:选取若干个,最大化比率。贪心考虑,只取所有权值为正的物品,其余同上。

代码:

using db = double;
const db eps = 1e-6;
int n, k, a[1010], b[1010];
db c[1010];
inline bool cmp(const db a, const db b) {
    return a > b;
} bool check(const db x) {
    for (int i = 1; i <= n; ++i) c[i] = a[i] - b[i] * x;
    sort(c + 1, c + n + 1, cmp); db s = 0;
    for (int i = 1; i <= n - k; ++i) s += c[i];
    return s > 0;
} signed main() {
    while (1) {
        n = rr, k = rr; if (!n && !k) break;
        for (int i = 1; i <= n; ++i) a[i] = rr;
        for (int i = 1; i <= n; ++i) b[i] = rr;
        db l = 0, r = 100, mid; while (r - l > eps) {
            mid = (l + r) / 2;
            if (check(mid)) l = mid;
            else r = mid;
        } printf("%d\n", int(mid * 100 + 0.5));
    } return 0;
}

最优比率生成树

题目:POJ2728 Desert King

题意:给定一棵图,每条边有两个权值 \(a_i,b_i\),求一棵生成树,使得 \(\dfrac{\sum_{e\in T}a_e}{\sum_{e\in T}b_e}\) 最小。

分析:与上一题很类似,把 \(a_i-b_i\times\text{mid}\) 作为每条边的权值,那么这个图的最小生成树就是 \(f(\text{mid})\) 最小值

代码:略。

最优比率生成环

题目:P3199 最小圈、P1768 天路

题意:给定一个图,每条边有价值 \(v_i\) 和费用 \(p_i\),求一个环,使得总价值与总费用的比值最小。

分析:我们二分一个答案 \(\text{mid}\),如果存在一个环,满足 \(\sum v/\sum p\ge\text{mid}\),那么移项一下就有 \(\sum v\ge\text{mid}\times\sum p\),就有 \(\sum v\ge\sum(\text{mid}\times p)\),也即存在一个环满足 \(\sum(\text{mid}\times p-v)\le0\),也就是把 \(\text{mid}\times p-v\) 作为新的边权,要判断图中是否存在负环。找负环可以用 SPFA 的 DFS 版本。

代码:

int SPFA(int u, double mid) {    // 判负环
    vis[u] = 1; for (int i = head[u]; i; i = e[i].nxt) {
        int v = e[i].v; double w = e[i].w - mid;
        if (dis[u] + w < dis[v]) {
            dis[v] = dis[u] + w; if (vis[v] || SPFA(v, mid)) return 1;
        }
    } vis[u] = 0; return 0;
} bool check(double mid) {       // 如果有负环返回 true
    for (int i = 1; i <= n; ++i) dis[i] = 0, vis[i] = 0;
    for (int i = 1; i <= n; ++i) if (SPFA(i, mid)) return 1;
    return 0;
}

应用

例题

题目:AT_abc324_f Beautiful Path(考前打比赛遇到的)。

题意:给定一个 \(n\) 个点 \(m\) 条边的有向图,保证 \(\forall i\in[1,n]:u_i<v_i\)。每条边有价值 \(b_i\) 和费用 \(c_i\),找一条路径 \(1\rightarrow n\),最大化 \(\sum b_i/\sum c_i\)

分析:二分一个答案 \(\text{ans}\),则有 \(\sum b_i/\sum c_i\ge\text{ans}\longrightarrow\sum b_i\ge\text{ans}\times\sum c_i\longrightarrow\sum b_i-\text{ans}\times\sum c_i\ge0\longrightarrow\sum(b_i-\text{ans}\times c_i)\ge0\),因此,以 \(b_i-\text{ans}\times c_i\) 为边权建图跑最短路即可。

代码:

const int N = 2e5 + 10;
const db eps = 1e-10, db INF = 1e18;
int n, m; struct node {
    int v, b, c;
}; vector<node> g[N];
db f[N]; bool check(db x) {
    for (int i = 1; i <= n; ++i) f[i] = -INF;
    f[1] = 0; for (int i = 1; i <= n; ++i)
        for (node j : g[i]) f[j.v] = max(f[j.v], f[i] + j.b - j.c * x);
    return f[n] > 0;
} signed main() {
    n = rr, m = rr;
    for (int i = 1, u, v, b, c; i <= m; ++i) {
        u = rr, v = rr, b = rr, c = rr;
        g[u].push_back({v, b, c});
    } db l = 0, r = 1e4; while (r - l > eps) {
        db mid = (l + r) / 2;
        if (check(mid)) l = mid;
        else r = mid;
    } printf("%.15lf", l);
    return 0;
}

练习题

见:https://www.luogu.com.cn/training/400462

Reference

[1] https://oi-wiki.org/misc/frac-programming/
[2] https://www.cnblogs.com/captain1/p/9929128.html文章来源地址https://www.toymoban.com/news/detail-711382.html

到了这里,关于基本技巧——分数规划 学习笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • PS CS6视频剪辑基本技巧(二)视频剪接和添加图片

    系列讲座导读 PS CS6视频剪辑基本技巧(一)CS6可以实现的视频剪辑功能 PS CS6视频剪辑基本技巧(二)视频剪接和添加图片 PS CS6视频剪辑基本技巧(三)添加声音和字幕 PS CS6视频剪辑基本技巧(四)字幕居中和滚动字幕 PS CS6视频剪辑基本技巧(五)添加logo、动画和画中画

    2023年04月15日
    浏览(52)
  • 异或运算的基本介绍以及使用技巧,剖析常见的异或题目

    异或运算,符号为‘^’,直接对底层二进制串进行运算,比算术运算快得多,规则为:相同为0,不同为1。 假设N为任意实数 性质1:0 ^ N = N 性质2:N ^ N = 0 性质3:异或运算满足交换律与结合律 重点:我们可以将异或运算理解为二进制的无进位相加!也就是说,当两个数异或

    2024年02月08日
    浏览(33)
  • 【Python beautifulsoup】详细介绍beautifulsoup库的使用方法,包括安装方式、基本用法、常用方法和技巧,以及结合lxml和parsel的具体使用场景和区别。

    Python beautifulsoup库是一个强大的Web抓取和解析库,它提供了丰富的功能和简单易用的API,可以帮助我们处理HTML和XML文档,从中提取数据,进行数据清洗和处理。beautifulsoup库基于Python标准库中的html.parser模块,同时还可以与第三方解析库lxml和parsel配合使用,提供更高效和灵活的

    2024年02月04日
    浏览(47)
  • 【002JavaScript 类继承】基本继承、调用父类方法和混入模式等方面的知识。掌握类继承的概念和技巧,提升代码的灵活性和可维护性。

    在 JavaScript 中,类继承是实现代码复用和扩展的重要概念。通过继承,我们可以基于现有类创建新类,并继承父类的属性和方法。本文将详细介绍 JavaScript 类继承的各个方面和技巧。 使用 extends 可以实现基本的类继承。 } class Dog extends Animal { bark() { console.log( ${this.nam

    2024年02月08日
    浏览(48)
  • 【大厂AI课学习笔记】【2.1 人工智能项目开发规划与目标】(7)特征工程的基本方法

    今天来学习特征工程的基本方法。 基本方法包括:特征选择(Feature Selection)、特征提取(Feature Extraction)和特征构建(Feature Construction)。 从给定的特征集合中选出相关特征子集的过程。 去除无关特征,降低特征学习难度,让模型简单,降低计算复杂度。 抛弃这部分特征

    2024年02月22日
    浏览(37)
  • Atcoder Beginner Contest 324 F Beautiful Path 题解-分数规划

    为了更好的阅读体验,请点击这里 分数规划小技巧: 尽可能将式子写成存在某种取值,使得不等式成立的形式。 不然可能需要绕几个弯才能想出来。 题目链接 题目大意:给出一个 DAG,每条边有一个 (b_i, c_i) ,保证从编号小的边向编号大的边连边,且 (1) 到 (n) 必有路径

    2024年02月08日
    浏览(27)
  • [USACO07DEC] Sightseeing Cows G(分数规划+负权回路判定)

    [USACO07DEC] Sightseeing Cows G - 洛谷 题目大意: 给出一张n点m边的带点权带边权的有向图 求一个回路使得路上点权和除以边权和最大(最优比率回路) 首先一定仔细读题,是回路不是路径 由于回路上所有点权只能获取一次,但边权会获取很多次,所以最优解一定是简单回路(无

    2024年02月10日
    浏览(236)
  • 第三章 图论 No.6负环之01分数规划与特殊建图方式

    裸题:904. 虫洞 904. 虫洞 - AcWing题库 这个==真的服,调半天,还有,邻接表的大小又设置错了 01分数规划:361. 观光奶牛 361. 观光奶牛 - AcWing题库 在图论问题中,所有形如:某个部分之和除以某个部分之和最大的问题,被称为01分数规划,通常使用二分解决这类问题 根据题意

    2024年02月13日
    浏览(30)
  • 全栈工程师基本的学习规划路线

    当你想成为一名全栈工程师时,以下是一个基本的学习规划路线,供你参考: 1. 前端开发 学习HTML、CSS和JavaScript的基础知识 掌握前端框架(如React、Angular或Vue.js)的使用 学习前端工具和构建工具(如Webpack、Gulp等)的使用 了解前端性能优化和响应式设计的技巧 2. 后端开发

    2024年02月10日
    浏览(44)
  • Unity学习笔记——ScrollView常用技巧

    在学习UI过程中反复接触ScrollView,遇到了很多使用问题,有许多技巧需要记录下来 如果不使用横向滑动,只需要将ScrollView中的Horizontal取消即可,虽然在Unity视图中还会存在,但运行游戏后就会消失;纵向滑动条同理 另外,如果你的Content的范围设置太小,也是不会显示滑动条

    2024年02月09日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包