第一篇:
动态规划(Dynamic Programming)
求解过程是多阶段决策过程,每步处理一个字问题,可用于求解组合优化问题
适用条件:问题要满足优化原则或最优子结构性质,即:一个最优决策序列的任何子序列本身一定是相对于子序列的初始和结束状态的最优决策序列
实例:最短路径问题
问题:
输入:
起点集合{S1,S2,…,Sn}
终点集合{T1,T2,…,Tn}
中间结点集,
边集E,对于任意边e有长度
输出:一条从起点到终点的最短路径
实例:
算法设计:
蛮力算法: 考察每一条从某个起点到某个终点的路径,计算长度,从其中找出最短路径。
上述实例中,如果网络层数为k,那么路径条数将接近2的k次方。
动态规划算法: 多阶段决策过程。
每步求解的问题是后面阶段求解问题的子问题。每步决策将依赖于以前步骤的决策结果。
动态规划求解:
优化原则:最优子结构性质
优化函数的特点:任何最短路的子路径相对于子问题始、终点最短
优化原则:一个最优决策序列的任何子序列本身一定是相对于子序列的初始和结束状态的最优决策序列
动态规划算法设计
动态规划设计要素
问题建模,优化的目标函数是什么?约束条件是什么?
如何划分子问题(边界)?
问题的优化函数值与子问题的优化函数值存在着什么依赖关系?(递推方程)
是否满足优化原则
最小子问题怎样界定?其优化函数值,即初始值等于什么?
动态规划算法设计要素小结
多阶段决策过程,每步处理一个字问题,界定子问题的边界
列出优化函数的递推过程及初值
问题要满足优化原则或最优子结构性质,即:一个最优决策序列的任何子序列本身一定是相对于子序列的初始和结束状态的最优决策序列
动态规划算法的递归实现
小结
与蛮力算法相比较,动态规划算法利用了子问题优化函数间的依赖关系,时间复杂度有所降低
动态规划算法的递归实现效率不高,原因在于同一子问题多次重复出现,每次出现都需要重新计算一遍。
采用空间换时间策略,记录每个子问题首次计算结果,后面再用时就直接取值,每个字问题只算一次。
动态规划算法的迭代实现
迭代计算的关键
每个子问题只计算一次
迭代过程
从最小的子问题算起
考虑计算顺序,以保证后面用的值前面已经计算好
存储结构保存计算结果–备忘录
解的追踪
递归和迭代这两种实现的比较
递归实现:时间复杂性高,空间较小
迭代实现:时间复杂性低,空间消耗多设计标记函数标记每步的决策
考虑根据标记函数追踪解的算法
原因:递归实现子问题多次重复计算,子问题计算次数呈指数增长,迭代实现每个子问题只计算一次。
动态规划时间复杂度:
备忘录各项计算量之和+追踪解工作量
通常追踪工作量不超过计算工作量,是问题规模的多项式函数
动态规划算法的要素
划分子问题,确定子问题边界,将问题求解转变成多步判断的过程。
定义优化函数,以该函数极大(或极小)值作为依据,确定是否满足优化原则。
列优化函数的递推方程和边界条件
自底向上计算,设计备忘录(表格)
考虑是否需要设立标记函数
总结:动态规划算法设计要点
引入参数来界定子问题的边界。注意子问题的重叠程度(动态规划之所以比蛮力算法好,效率高,是在于它的每一个子问题子算一次,如果动态规划算法里面,它的子问题出现次数非常少,前面存放着,后面几乎不再引用,这时相当于跟蛮力算法就没有太大区别了。所以只有字问题呗多次重叠出现,后面计算的时候多次要调用这个值,这个时候动态规划算法才能体现出它的时间效率)。
给出带边界参数的优化幻术定义与优化函数的递推关系,找到递推关系的初值。
判断该优化问题是否满足优化原则。
考虑是否需要标记函数。
采用自底向上的实现技术,从最小的子问题开始迭代计算,计算中用备忘录保留优化函数和标记函数的值。
动态规划算法的时间复杂度是对所有字问题(备忘录)的计算工作量求和(可能需要追踪解的工作量)
动态规划一般使用较多的存储空间,这往往成为限制动态规划算法使用的瓶颈因素。(空间换时间)
更多关于hadoop,spark和机器学习,数据结构与算法文章请关注本文公众号: