2019暑期集训 - Day 11
我似乎确凿好像的确听懂了 . . . 一丢丢???
整理了一些东西,搬上来
贪心
贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。
贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。
贪婪算法可解决的问题通常大部分都有如下的特性:
- 随着算法的进行,将积累起其它两个集合:一个包含已经被考虑过并被选出的候选对象,另一个包含已经被考虑过但被丢弃的候选对象。
- 有一个函数来检查一个候选对象的集合是否提供了问题的解答。该函数不考虑此时的解决方法是否最优。
- 还有一个函数检查是否一个候选对象的集合是可行的,也即是否可能往该集合上添加更多的候选对象以获得一个解。和上一个函数一样,此时不考虑解决方法的最优性。
- 选择函数可以指出哪一个剩余的候选对象最有希望构成问题的解。
- 最后,目标函数给出解的值。
为了解决问题,需要寻找一个构成解的候选对象集合,它可以优化目标函数,贪婪算法一步一步的进行。起初,算法选出的候选对象的集合为空。接下来的每一步中,根据选择函数,算法从剩余候选对象中选出最有希望构成解的对象。如果集合中加上该对象后不可行,那么该对象就被丢弃并不再考虑;否则就加到集合里。每一次都扩充集合,并检查该集合是否构成解。如果贪婪算法正确工作,那么找到的第一个解通常是最优的。
贪心算法的核心就是贪心选择。贪心选择是指所求问题的整体最优解可以通过一系列局部最优的选择。对于一个具体问题,要确定它是否具有贪心选择的性质,我们必须证明每一步所作的贪心选择最终能得到问题的最优解。通常可以首先证明问题的一个整体最优解,是从贪心选择开始的,而且作了贪心选择后,原问题简化为一个规模更小的类似子问题。然后,用数学归纳法证明,通过每一步贪心选择,最终可得到问题的一个整体最优解。
许多题目都会用到贪心的思想,但贪心常常会伴随着动态规划等算法出现,使得其隐蔽性很高,并且,码出来的贪心还不一定正确,一是有些看似贪心的题其实不适用贪心,二是许多时候贪心思路不正确。在赛场上,一般没时间证明,一般只能试试能不能举出反例(说不定可以拿来骗分)。贪心也有难有易,可以把贪心出得简简单单,也可以刻意用它刁难人。
分治
分治,字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。
在计算机科学中,分治法就是运用分治思想的一种很重要的算法。分治法是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)等等。
采用分治法解决的问题一般具有的特征如下:
- 问题的规模缩小到一定的规模就可以较容易地解决。
- 问题可以分解为若干个规模较小的模式相同的子问题,即该问题具有最优子结构性质。
- 合并问题分解出的子问题的解可以得到问题的解。
- 问题所分解出的各个子问题之间是独立的,即子问题之间不存在公共的子问题。
分治算法一般分为 3 步:
- 分:把输入的问题划分为 \(k\) 个子问题,并尽量使这 \(k\) 个子问题的规模大致相同。
- 治:递归求解 \(k\) 个子问题。
- 合:把 \(k\) 个子问题的解合并,得到主问题的解。
分治的重点在"合"这一步,这一般是分治的难点,也是决定算法时间复杂度的重点。一般这一步会采用枚举的方式,有时会加上前缀和等优化,得到跨越不同子问题的位置对答案的贡献。
一般而言,当"合"这一步的时间复杂度为 \(O(T)\) 时,求解整个大小为 \(N\) 的问题的时间复杂度将为 \(O(T\log N)\) 。

浙公网安备 33010602011771号