感谢 $ \text{orzws/chy} $ 倾情授课。

贪心与动态规划的一个使用条件是无决策后效性。这个我暂时不大理解,没法写总结

然后就是贪心的一些证明方式。听说很多时候贪心是猜后证明的,然后我可以不证明 对拍试试正确性是么.jpg

-1. 证明方式

  1. 微扰:见下 排序贪心;

  2. 反证法;

  3. 数学归纳法;

  4. 局部最优作用范围扩展不会使得整体更劣;

  5. 决策包容性:作出局部最优决策后,问题状态空间中的可达集合包含了作出其他任何决策后的可达集合。见下 反悔贪心。


0. 朴素贪心

AT2557 [ARC073C] Ball Coloring

所有球中标的最大与最小值一定会被选中,根据此分类讨论。

钦定 \(max\) 取红色,若:

  1. \(min\) 取蓝色。那么剩下的贪心,小的给蓝,大的给红。

  2. \(min\) 取红色。那么剩下的枚举最小值然后二分最大值,经典求最小极差法。

P2587 [ZJOI2008]泡泡堂

大型田忌赛马(?)

爷的做法:

暴力 \(set\) 日一下()

优先拿小的去日。

题解做法:

最好的情况是,优先用弱的去赢弱的,打不过就看最强的能不能打过最强的,不行就替补()

最坏的情况是,把两支队伍反过来就可以了。


1. 排序

既然是排序我们就需要关键字

大致做法是这样的。只考虑相邻两者交换的影响,列不等式求解,得到需要用来排序的关键字。

或者说假设一个最优解,将最优解的邻项交换,看看答案会不会变劣。

(这个叫邻项交换法,也叫微扰?)

AT2672 [AGC018C] Coins

既然有三个选项,不妨缩成两个()

假设全都选了金币(\(A\))

设 \(f_i=B_i-A_i\),\(g_i=C_i-A_i\)

现在就要选 \(y\) 个人选 \(f\) , \(g\) 个人选 \(g\) 。

考虑 \(i\) ,\(j\) 两者, \(i\) 选 \(f\) , \(j\) 选 \(g\) 比 \(i\) 选了 \(g\) , \(j\) 选了 \(f\) 更优,则:

\[f_i+g_j \geq f_j+g_i
\]

即:

\[f_i-g_i \geq f_j-g_j
\]

所以按 \(f-g\) 排个序就好了。

P2123 皇后游戏

浅谈邻项交换排序的应用以及需要注意的问题 By ouuan

忘了先讲国王游戏辽。

皇后游戏中,大臣获得的奖金数目是递增的,我们要使得\(c_n\)尽可能小。

影响\(c_i\)的只有\(c_{i-1}\),前\(i-1\)个数的顺序并不产生额外影响。前缀子问题最优可推到全局最优。

考虑邻项\(i\),\(j\)交换。设\(i\),\(j\)的前一个获得奖金为\(K\),他们前面所有人的\(a\)值和为\(S\),则:

  1. 当\(i\)在\(j\)之前时:
\[c_i=max\{K,S+a_i\}+b_i
\]
\[c_j=max\{c_i,S+a_i+a_j\}+b_j
\]
  1. 当\(j\)在\(i\)之前时:
\[c_j=max\{K,S+a_j\}+b_j
\]
\[c_i=max\{c_j,S+a_j+a_i\}+b_i
\]

当\(i\)在前比\(j\)在前更优:

\(max\{K+b_i+b_j,S+a_i+b_i+b_j,S+a_i+a_j+b_j\}<max\{K+b_i+b_j,S+a_j+b_i+b_j,S+a_i+b_i+a_j\}\)

\(k+b_i+b_j\)那项可以直接去掉了。对于剩下的项,取负再加上\(S+a_i+b_i+a_j+b_j\),得到:

\[min\{a_j,b_i\}>min\{a_i,b_j\}
\]

经过一系列我看不下去的证明,这个比较是有传递性的。

听说直接把这个比较扔进cmp函数也能过。我感觉会\(RE\)(?)

严格弱序

std::sort中比较符必须有的性质,具体如下:

  1. 非自反性(自己跟自己比较为false)

  2. 非对称性(若x与y比较为true,则y与x比较为false)

  3. 传递性(若x与y比较为true,y与z比较为true,则x与z比较为true)

  4. 不可比性的传递性(若x与y互相比较为false,y与z互相比较为false,则x与z互相比较为false)

对,他是没有不可比性的传递性的。

优化的话,由于\(a\)的前缀和可能影响全局答案,优先把\(a\)较小的放前面。

证不动正确性了。;w;

P1248 加工生产调度


2. 数据结构维护相关信息


3. 反悔贪心

贪心的时候,需要注意的是,一定只考虑相邻一步的操作。一些题目确实需要把看起来多样繁琐的操作拆成单位简单操作叠加作用的结果。

仔细思考了一下反悔贪心的原理。一般来说需要一个优先队列,来存储接着某项直接操作/反悔操作的增益

这种贡献是逐步累加的,直到大根堆堆头 $ \leq 0 $ 。

重新百度了一下((),反悔贪心大致是分为反悔堆反悔自动机

反悔堆

通过堆来维护当前贪心策略最优解。

USACO09OPEN 工作调度Work Scheduling

有 $ n $ 项工作,每 $ i $ 项工作有一个截止时间 $ D_i $ ,完成每项工作可以得到利润 $ P_i $ ,求最大可以得到多少利润。

比较基础。按照 $ D_i $ 排序,能做的工作就做,然后以 $ P_i $ 作为关键字放入小根堆。遇到不能做的工作,取出堆顶,如果 $ P_i>top $ 就换掉。

CF436E Cardboard Box

反悔堆的一个常见做法。把可行的各种下一步的策略分别放到不同的堆里面。

比如这道题,从 \(i\) 个星星到 \(i+1\) 个星星就有如下取法:

  1. 从未取星星的一关 \(i\) ,获取一个星星,代价 \(a_i\);

  2. 从取了一颗星星的一关 \(i\),再获取一个星星,代价 \(b_i-a_i\);

  3. 从取了一个星星的一关 \(i\),把星星扔回去,取另一个未取星星一关 \(j\) 的两个星星,代价 \(b_j-a_i\);

  4. 从取了两个星星的一关 \(i\),把星星扔回去一个,取另一个未取星星一关 \(j\) 的两个星星,代价 \(b_j-(b_i-a_i)\)。

每次取代价最小一个就行了。

具体的实现细节上,维护的是:

  1. 未取星星关的 \(a_i\)(操作1);

  2. 未取星星关的 \(b_i\)(操作3,4)

  3. 取一星星关的\(b_i-a_i\)(操作2);

  4. 取一星星关的\(-a_i\)(操作3);

  5. 取两星星关的\(a_i-b_i\)(操作4)。

要把堆中不符合 \(type\) 的数值 \(pop\) 掉。可以看一下这位的实现,写的不错(?)

AT2672 [AGC018C] Coins

重新再看一下这个题。

假设先任意选择。对于三个不同选择的人 \(i\) \(j\) \(k\),反悔的操作可能有:

  1. \(i \longleftrightarrow j\) (\(B_i-A_i+A_j-B_j\))

  2. \(j \longleftrightarrow k\) (\(C_j-B_j+B_k-C_k\))

  3. \(i \longleftrightarrow k\) (\(C_i-A_i+A_k-C_k\))

  4. \(i \longrightarrow j \longrightarrow k \longrightarrow i\) (\(B_i-A_i+C_j-B_j+A_k-C_k\))

  5. \(i \longrightarrow k \longrightarrow j \longrightarrow i\) (\(C_i-A_i+B_k-C_k+A_j-B_j\))

具体的维护:

  1. 选了 \(A\) 的 \(B_i-A_i\),\(C_i-A_i\)

  2. 选了 \(B\) 的 \(A_i-B_i\),\(C_i-B_i\)

  3. 选了 \(C\) 的 \(A_i-C_i\),\(B_i-C_i\)

反悔自动机

一般是过程中累积贡献,通过差值消去中间项(反悔)来快速得到全局最优解。

CF865D Buy Low Sell High

基本的贪心思路是:买入价格最小的股票,在能赚钱的时候卖出。

当然这个是错的()

之前也写过一个类似的题目(纪念品/股票市场),由于一天之内价格不会变动,所以可以假装我们先卖了,然后再买进来,之后再卖掉。对于 $ i \leq j \leq k $ ,具体的表现形式是:

$ (p_k-p_j)+(p_j-p_i)=p_k-p_i $

先买入 $ i $ ,再在 $ j $ 卖出,获得 $ p_j-p_i $ 的贡献。然后对于 $ j $ ,接下来有两步可能的操作:

  1. 在 $ p_j $ 又买回来,再往后考虑。

  2. 在 $ p_j $ 又买回来(相当于在 $ j $ 啥都没干)后,再买 $ p_j $ 。

于是我们可以在队列里面塞两遍 $ p_j $ 。

  1. 如果贡献加了一次 $ p_k-p_j $ ,表示 $ j $ 反悔,在 $ i $ 买在 $ k $ 卖;

  2. 如果贡献加了一次 $ p_{k_1}-p_j $ ,再加一次 $ p_{k_2}-p_j $ ,表示 $ j $ 先反悔,再 $ j $ 买 $ k_2 $ 卖。

P1792 [国家集训队]种树

反悔自动机,做法是把所有选项扔进堆里,取出堆头 $ b $ ,把与 $ b $ 相邻的两项 \(a\),\(c\) 合成一个新点 \(a+c-b\),再扔回堆里面。

看完题解还是纠结了半天两个问题:

  1. 这个反悔存储方式是否覆盖了所有可能的下一步

  2. 或者未存储的反悔策略不可能成为最优的答案

浅列了一下情况。

【Note】贪心的更多相关文章

  1. OJ题解记录计划

    容错声明: ①题目选自https://acm.ecnu.edu.cn/,不再检查题目删改情况 ②所有代码仅代表个人AC提交,不保证解法无误 E0001  A+B Problem First AC: 2 ...

  2. 【Codeforces 738D】Sea Battle(贪心)

    http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...

  3. CF733C Epidemic in Monstropolis[模拟 构造 贪心]

    C. Epidemic in Monstropolis time limit per test 1 second memory limit per test 256 megabytes input s ...

  4. CF732D. Exams[二分答案 贪心]

    D. Exams time limit per test 1 second memory limit per test 256 megabytes input standard input outpu ...

  5. CodeForces 485C Bits[贪心 二进制]

    C. Bits time limit per test1 second memory limit per test256 megabytes inputstandard input outputsta ...

  6. leetcode bugfree note

    463. Island Perimeterhttps://leetcode.com/problems/island-perimeter/就是逐一遍历所有的cell,用分离的cell总的的边数减去重叠的 ...

  7. UVALive 7147 World Cup(数学+贪心)(2014 Asia Shanghai Regional Contest)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...

  8. CF722D. Generating Sets[贪心 STL]

    D. Generating Sets time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  9. 【CodeForces 589F】Gourmet and Banquet(二分+贪心或网络流)

    F. Gourmet and Banquet time limit per test 2 seconds memory limit per test 512 megabytes input stand ...

  10. hdu5037 Frog (贪心)

    http://acm.hdu.edu.cn/showproblem.php?pid=5037 网络赛 北京 比较难的题 Frog Time Limit: 3000/1500 MS (Java/Othe ...

随机推荐

  1. Vue组件template中html代码自动补齐设置

    1.vscode设置==>扩展==>JSON==>在settings.json中编辑 2.在最后 } 前添加如下代码保存文件即可 // 自动补全模板字符串 "emmet.t ...

  2. ybtoj 12F

    求值的话改为求解前缀和的值,通过两个前缀和相减即可得到每个值. 每次询问相当于给一个方程. 一共有 $n$ 个未知数,因此需要 $n$ 个方程,同时每个数都必须至少在方程中出现一次. 最小生成树求解即 ...

  3. oracle表名中带@什么意思,例如:select * from dim.dim_area_no@to_dw

    转载自:https://zhidao.baidu.com/question/259154968.html @是调用数据库链接(database link)的意思. 数据库链接的作用是从a数据库到b数据 ...

  4. Ndisuio win10 注册表下载

    看了一下应该没有什么隐私内容,丢失这个注册表信息会让网络服务无法启动,新建txt,复制后修改后缀为.reg,双击录入,在管理员权限下cmd中输入 netsh winsock reset 重启 Wind ...

  5. Bootstrap4布局(简要)

    目录 什么是Bootstrap 布局基础 布局容器 相应断点 z-index 网格系统 12栅格 重排序 列偏移 弹性盒子 什么是Bootstrap Bootstrap是目前最流行的一套前端开发框架, ...

  6. 探秘ThreadLocal

    一 类结构 主要是set(T), get(), remove()方法 二  TheadLocal是什么时候创建的 threadLocal的初始化, lazy creating, 用到的时候(get 或 ...

  7. day49-数据类型、约束条件

    数据类型: 1.整型--默认情况下都是带有符号的, id int(8)-- 如果数字没有超过9位,默认用0填充,如果数字超出8位,有几位存几位 总结:针对整型字段,括号内无需指定宽度,因为它默认的宽度 ...

  8. 如何启动MySQL?

    参见链接:https://www.cnblogs.com/Yanjy-OnlyOne/p/12603117.html

  9. 02 docker的基本用法

    本章内容 1.OCI 2.docker核心组件--Cgroup与runC 3.docker的架构 4.docker的基本操作 5.安装docker环境 6.创建第一个容器 6.docker容器的状态变 ...

  10. 会长哥哥帮助安装ubuntu

    今晚突然想到要安装虚拟机,因为我原来上的python预科班里面讲解安装虚拟机,但是我当时没有安装上,导致预科班后面的课我没听懂,今天听课讲到字符和编码 所以想到了我的虚拟机,于是今晚很谨慎的求助会长大 ...