There is a confusing question, i.e. the name of this method is dynamic programming, how can we understand it ? The dynamic programming in chinese is "动态规划", to be honest, this translation is imprecise, because we can't get the real thinking of the this algorithm. The programming refers to a tabular method, according to the next context, we will understand what is a tabular method.

10月29日思考

根据目前的理解,动态规划法这一名称本身带给人极大的困惑,一个更贴合实际的名称应当是动态表格法。 为什么称之为动态表格?表格具备存储功能,dp实际就是通过利用空间存储来减少时间的一种方式。动态而非静态原因在于随着程序的运行,表格的内容一直在发生更改,所以是动态表格而非静态表格。 动态规划问题解决的一般是仅要结果不要方案的问题,一般外表表现为求解最大值,最小值等。

动态规划的思想就是将一个问题分解为若干个子问题,再通过子问题的最优解构造出问题的最优解。 先找子问题,但是有一个问题:子问题和原问题不过是规模不同而已,问题类型并没有变,我要是能够轻松找到子问题,我为何不知道原问题该怎么解 从下面这个说法来看,所谓找到子问题实际是从多阶段决策过程中随便找一个单阶段的决策问题,然后转而去考虑两件事情

  1. 考虑在这个单阶段的决策问题中的所有可能涉及到的决策以及如何处理
  2. 如何利用这一阶段的决策结果去求解下一个阶段的决策问题

动态规划方法的原理就是把多阶段决策过程转化为一系列的单阶段决策问题,利用各个阶段之间的递推关系,逐个确定每个阶段的最优化决策,最终堆叠出多阶段决策的最优化决策结果。

以最长上升字序例为例,我们要求解的是所有子序列中的最长的长度 那么整个搜索空间就是所有子序列,目标值是长度最大值 然后为子序列找到标识的方法,用子序列的最后一个字符作为分类标准(为何选择最后字符,这个目前还不清楚) 然后你就会发现,按照最后一个字符对全集进行分类后,我们实际就找到了子问题是什么 原问题是在所有子序列中找到最大长度,而子问题就是在以一个确定位置作为最后一项的所有子序列中找到最大长度 然后我们就可以在多个子问题的解中,寻找到原问题的解,相当于用子问题的解推导出了原问题的解 这里提到的这种由子问题的解推导原问题的解的方式就类似已知各个班级的成绩最高分,确定整个学校的成绩最高分

最开始的思路实际是从集合划分的角度考虑的,需要将搜索空间这个全集划分为不同的子集(这不刚好对应寻找子集的过程吗)

什么叫做思考子问题,其类似考虑一个特定的时刻或者情景,考虑此时应当做出何种决策 一般地, 我们用dp数组(dp table)来保存子问题的结果(进一步印证了动态表格法的说法) 数组只是负责存储,用几维,每一维度是何含义,这些都是子问题是什么来决定的

求解动态规划的核心问题是穷举,但是难在穷举所有可行解不是一件容易的事 动态规划问题的一般形式就是求最值

要符合「最优子结构」,子问题之间一定是无关的。子问题无关是指同一个原问题的一个子问题的解不影响另一个子问题的解(《算法导论》p232),而无关的根本原因在于子问题之间不会共享资源

找最优子结构的过程,其实就是证明状态转移方程正确性的过程,方程符合最优子结构就可以写暴力解了,写出暴力解就可以看出有没有重叠子问题了,有则优化,无则 OK。

要证明最优子结构,一定是得先把子问题确定下来,在最短简单路径问题中,通过引入中间节点,把u->v原问题,分解为u->p和p->u两个子问题 然后再去证明最优子结构

流程

具体内容的描述基于活动选择问题

  1. 根据题意,确定我们的寻找目标。即一个最大兼容活动集
  2. 需要能够考虑到这一最大兼容活动集能够划分为子活动集,也就是说源问题可以划分为子问题(此步骤在算法导论中并没有单独提及,只是我的理解,也是我目前感觉比较困难的一步)
  3. 只有上一步骤中判断出源问题能够划分为子问题,这个问题才可能具备最优子结构性质
  4. 验证问题具备最优子结构性质(通过剪切-粘贴法)
  5. 在第2步中,如果能够想到源问题划分为子问题的方法,那么同时也就能够得到一个递归表达式,通过此递归表达式就能够对问题进行求解

到此,就是动态规划的流程。

然而在某些问题中,比如活动选择问题,动态规划的解法是可以演变为贪心策略的解法的。 而动态规划转为贪心的入手点在于动态规划的缺点,从递归表达式可以看出,它需要对所有子问题进行考察后才能进行选择。 那么考虑能否不考察子问题,直接做出一个选择。贪心策略就是要求这一步我们做出一种直觉上正确的选择,然后去证明这种选择正确性

在完整的证明之前,我们并不能够确定能够转为贪心解法。

官方说法

在发掘最优子结构性质的过程中,实际上遵循了如下的通用模式:

  1. 证明问题最优解的第一个组成部分是做出一个选择,例如,选择钢条第一次切割位置, 选择矩阵链的划分位置等。做出这次选择会产生一个或多个待解的子问题。
  2. 对于一个给定问题,在其可能的第一步选择中,你假定已经知道哪种选择才会得到最优解。你现在并不关心这种选择具体是如何得到的,只是假定已经知道了这种选择。
  3. 给定可获得最优解的选择后,你确定这次选择会产生哪些子问题,以及如何最好地刻画 子问题空间。
  4. 利用“剪切—粘贴" (cut-and-paste) 技术证明:作为构成原问题最优解的组成部分,每个子问题的解就是它本身的最优解。证明这一点是利用反证法:假定子问题的解不是其自身的最优解,那么我们就可以从原问题的解中“剪切"掉这些非最优解,将最优解"粘贴”进去,从而得到原问题一个更优的解,这与最初的解是原问题最优解的前提假设矛盾。如果原问题的最优解包含多个子问题,通常它们都很相似,我们可以将针对一个子问题的"剪切—粘贴“论证方法稍加修改,用于其他子问题。

性质

  1. 最优子结构 (optimal substructure) 性质:问题的最优解由相关子问题的最优解组合而成,而这些子问题可以独立求解。或者说可以从子问题的最优结果推出更大规模问题的最优结果

optimal substructure: optimal solutions to a problem incorporate optimal solutions to related subproblems, which we may solve independently

最优子结构简单来说可以认为是,原问题的最优解中随便抽出来的一部分,一定是这部分子问题的最优解。如果不是这部分子问题的最优解,那么用它的最优解去替换非最优,就可以使得原问题的解更优。(这一方法在《算法导论》中被称之为剪切-粘贴法(cut-and-paste technique))。

从这个描述也可以看出,最优子结构无论是证明还是理解,非常关键的一点就是解之间是可以相互替换的,即我们可以随意更换子问题的解但是这只会影响全局解的值,并不是不能操作。这就要求前后操作之间不能存在依赖关系,任何一个时刻后的动作,并不关心此前的动作是如何做的,它只关心此前动作产生的结果是多少。

贪心算法是以动态规划方法为基础的,在每个贪心算法之下,几乎总有一个更繁琐的动态规划算法(从活动选择问题的分析流程可以看出,贪心是根据某些问题特点,简化了动态规划算法需要检查全部子问题才能进行选择的过程,直接进行选择)

所以是否可以认为贪心策略是可以从动态规划的解法而来的? 如果答案是肯定的,那么这将意味着我们可以把运用动态规划和贪心解决问题的步骤进行统一化,只需要按照固定的思考模式,首先接触到的是动态规划解法,然后根据实际条件,发展到贪心方法

贪心算法和动态规划不同之处在于:是否需要考虑子问题的解 贪心算法并不考虑子问题,直接在当前步骤中做出选择,选择之后才会求解子问题 动态规划无论是自底向上,还是自顶向下携带备忘机制,都需要先求解子问题,然后再进行选择

并且二者的一般求解顺序并不相同

  1. 贪心算法一般采用自顶向下顺序进行求解(动态规划同样可以采用自顶向下,但是动态规划的选择一定是发生在子问题被求解之后才发生的,因此采用自顶向下时,动态规划采用的方法一般就是递归,发展的路径是一颗树,也正是因为如此,为了减少重复子问题的计算,才需要搭配备忘机制使用。而贪心算法的选择并需要等待子问题的求解,因此并不需要递归,发展的路径是一个线性路径)
  2. 动态规划一般采用自底向上顺序进行求解

能使用贪心算法必须具备的两点性质

  1. 贪心选择性质 :只需要考虑当前局面的最优解,无需考虑子问题的解
  2. 最优子结构:同动态规划提到的最优子结构

无后效性:从不同的路径走到一个共同状态,而后续的状态变迁都是一样的,和之前采用何种路径到这个状态没有关系,即前面的各种决策结果由这个状态表示,在考虑后半段的决策方面没有任何区别

贪心算法设计步骤

  1. 将最优化问题转化为这样的形式:对其做出一次选择后,只剩下一个子问题需要求解。
  2. 证明做出贪心选择后,原问题总是存在最优解,即贪心选择总是安全的。
  3. 证明做出贪心选择后,剩余的子问题满足性质:其最优解与贪心选择组合即可得到原问题的最优解,这样就得到了最优子结构。

贪心和动态规划都会考虑到子问题,区别在于: 动态规划需要考虑在多个子问题中进行选择,但是贪心算法只需要考虑一个选择

贪心需要证明的是,每个步骤中采用的贪心策略,都能保证生成全局最优解,或者说它们都是全局最优解的一部分

所需性质

  • 同贪心算法相比,动态规划仅需要具备最优子结构性质
  • 贪心算法的复杂度是要优于动态规划的,那么所需的条件自然也会更严苛。在最优子结构性质之外,还需要具备贪心选择性质

选择问题的贪心策略证明方法

数学归纳法

采用数学归纳法,证明当进行到任意一个步骤时,都一定存在一个最优解包含上述所选择的内容

示例:

  1. 贪心算法 ppt p4 活动选择问题的证明
  2. hw3基站选址问题的证明

感觉他们的证明模式都需要利用到一个特点,就是每一步的选择都是一种最值,像活动选择问题选择的是结束时间最早的活动,基站选址问题选择的是所有可能位置中最靠后的位置

在数学归纳法的证明过程中,需要多次利用到这一最值属性

交换论证法

  1. 存在一贪心算法产生的解x,假设它不是最优解
  2. 正因为假设了x不是最优,所以才一定会存在一个比贪心算法产生的解更优的解y
  3. 构造有一个可行解z,z比y更优 这一个z,可以作为下一轮的y,同时不断向x靠近,不断重复直至同x相同 但是在演变过程中,答案是在不断优化的,说明最后得到了一个和x形式完全相同但又更优的解,说明最初的假设存在问题,即贪心算法产生的解是最优解

以上过程是《陈玉福算法讲义》中p74对分数背包问题的证明过程

实际上,它并没有很好的体现出交换论证法这种方法的核心理念 交换论证法的通用模型可以表述为

  1. 存在一贪心算法产生的解x,假设它不是最优解(注意这里的假设很关键,这一假设是整个论证过程中做过的第一个且唯一一个假设,而后的所有推论都是基于这一假设,最后发现矛盾时推翻的也是这一假设)
  2. 由于x不是最优解,所以一定存在一个比x更优的解y(这一步是基于上一步的假设)
  3. 交换y中的某些元素,可以使得答案更优
  4. 不断重复进行交换,最后解的形式会和x完全等价

矛盾点在于,一个和x完全等价的解具有更优的答案。因此证明假设是错误的,x一定是最优解