📅  最后修改于: 2020-12-10 06:27:46             🧑  作者: Mango
动态编程介绍
动态编程是解决优化问题的最强大的设计技术。
分而治之算法将问题划分为不相交的子问题,然后递归地解决子问题,然后结合它们的解决方案来解决原始问题。
当子问题不是独立的时,例如当它们共享相同的子问题时,将使用动态编程。在这种情况下,分治法可能会做比必要的事情更多的工作,因为它可以多次解决同一个子问题。
动态编程只解决一次每个子问题,并将结果存储在表中,以便在需要时可以重复检索它。
动态编程是一种自下而上的方法-我们解决所有可能的小问题,然后结合以获得更大问题的解决方案。
动态规划是算法设计的一种范式,其中,通过实现子问题解决方案以及出现“最优原理”的组合来解决优化问题。
动态编程的特点:
当问题具有以下特征时,动态编程将起作用:
- 最优子结构:如果最优解决方案包含最优子解决方案,那么问题将表现出最优子结构。
- 子问题重叠:当递归算法将重复访问相同的子问题时,则问题将具有子问题重叠。
如果问题具有最佳子结构,则可以递归定义最佳解决方案。如果一个问题具有重叠的子问题,那么我们可以通过仅计算每个子问题一次来改进递归实现。
如果问题没有最佳子结构,则没有基础来定义递归算法以找到最佳解决方案。如果一个问题没有重叠的子问题,那么使用动态编程将无济于事。
如果子问题的空间足够大(即输入大小为多项式),则动态编程比递归更有效。
动态编程的要素
基本上,三个要素是动态编程算法的特征:
- 子结构:将给定问题分解为较小的子问题。用较小问题的解决方案来表达原始问题的解决方案。
- 表结构:解决了子问题后,将结果存储到表中的子问题中。这样做是因为子问题解决方案已被多次重用,并且我们不想一遍又一遍地重复解决相同的问题。
- 自下而上的计算:使用表格,将较小的子问题的解决方案组合起来,以解决较大的子问题,并最终得出解决问题的解决方案。
注意:自下而上是指:-
- 从最小的子问题开始。
- 将它们的解决方案结合起来,可以解决规模越来越大的子问题。
- 直到解决原始问题为止。
动态编程的组成部分
- 阶段:问题可以分为几个子问题,称为子阶段。阶段是给定问题的一小部分。例如,在最短路径问题中,它们是由图的结构定义的。
- 状态:每个阶段都有几个与之相关的状态。最短路径问题的状态是到达的节点。
- 决策:在每个阶段,可以有多个选择,应从中做出最好的决定之一。在每个阶段做出的决定都应该是最佳的;这称为阶段决策。
- 最优政策:这是一个决定每个阶段决策的规则;如果策略是全局最优的,则称为最优策略。这被称为最佳贝尔曼原理。
- 给定当前状态,其余每个状态的最佳选择均不取决于先前的状态或决策。在最短路径问题中,没有必要仅知道我们如何获得节点。
- 考虑到阶段j + 1已解决,因此存在一种递归关系,该关系确定阶段j的最佳决策。
- 最后阶段必须自己解决。
动态规划算法的发展
它可以分为四个步骤:
- 表征最佳解决方案的结构。
- 递归定义最佳解决方案的值。与“分而治之”一样,将问题递归分为两个或多个最佳部分。这有助于确定解决方案的外观。
- 从下至上计算最佳解决方案的价值(从最小的子问题开始)
- 从较小的子问题的计算值构造整个问题的最佳解决方案。
动态编程的应用
- 0/1背包问题
- 数学优化问题
- 所有对最短路径问题
- 可靠性设计问题
- 最长公共子序列(LCS)
- 飞行控制和机器人控制
- 分时:计划工作以最大化CPU使用率