感谢 $ \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. 关于在Eclipse中使用EclEmma

    在LAB2中,要求使用EclEmma来统计JUnit测试用例的代码覆盖度.下面就来说说如何进行基本的使用来应付实验(bushi). 在这给出完全体,可以访问下面的网址进行学习. http://www. ...

  2. LeetCode刷题感想之滑动窗口

    发现滑动窗口也是一种经典解题思路,这一篇简单聊一下滑动窗口. 通常在碰到求XX子数组,子字符串,连续XX等题眼,可以考试用滑动窗口的思路来解决问题. 窗口的类型有几种: 1. 固定长度的窗口. 2. ...

  3. 解决element-ui表格多重嵌套循环时,添加row-key="id" 出现Duplicate keys detected: 'XXX' 错误的问题

    Duplicate keys detected: 'XXX' 错误,怀疑是多重嵌套循环时 :key="item.id或index" 不能重复的问题,但设置了不同的 key 后并未解 ...

  4. 工作随笔1-从slave备份,恢复成新得从库

    innobackupex --slave-info --safe-slave-backup --no-timestamp tmp_lastinnobackupex --apply-log tmp_la ...

  5. hdu: Dire Wolf(区间DP)

    Problem DescriptionDire wolves, also known as Dark wolves, are extraordinarily large and powerful wo ...

  6. vue项目部署后页面加载首次很慢的优化方案

    参考: vue项目首次加载特别慢需要怎么配置? 1.看看你的依赖包是不是全局引入的,改为组件内按需引入,可大大降低加载时长.或者将组件引入方式改为cdn引入.需要注意的是,两种引入方式不能共存. 2. ...

  7. linux查看IP地址

    方法一:ifconfig -a 方法二:ip addr

  8. 微信小程序 真机调试白屏

    真机调试白屏,报define is not defined 解决:   更新小程序版本

  9. Python第八章实验报告

    一.实验对象:<零基础学Python>第八章的3道实例和4道实战 二.实验环境:IDLE Shell 3.9.7 三.实验要求:学习使用标准模块和第三方模块 四.实验过程: 实例01 创建 ...

  10. 解决ssh $host jps bash: jps: command not found 问题

    问题描述 使用 ssh $host jps 命令报错,连本机也会有这样的情况,但是分开使用并没有问题,即ssh $host下执行jps命令并不会报错. 原因 因为ssh远程连接到服务器的环境变量中不包 ...