动态规划(dp)
下面是我关于动态规划的一点理解,纯文本无代码。
有时候光看是不行的,所以想写一写让自己理解一下。
一.什么叫动态规划
在研究多阶段决策过程的优化问题时,提出把多阶段过程转化为一系列单阶段的问题,利用各阶段之间的关系。
动态规划的关键是状态转移方程,即如何由以求出的局部最优解来推导全局最优解也就是利用状态转移方程来逐步求得多阶段问题的最优解。
多阶段 = =分解= => 单阶段;
单阶段的解 = =状态转移= => 多阶段的解
二.动态规划的基本思路
在这里引用百度百科上面的一段话:
其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。我们可以用一个表来记录所有已解的子问题的答案。不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。
在上面我们能知道就像之前动态规划里面的背包问题一样,利用填表来直观有效的解决。
至于如何找到状态转移方程,就看母问题和子问题之间的关系来写。
三.动态规划的特点及理解
1.动态规划问题的三个特点
1.无后效性:
将各阶段按照一定的次序排列好之后,对于某个给定的阶段状态,它以前各阶段的状态无法直接影响它未来的决策,而只能通过当前的这个状态。换句话说,每个状态都是过去历史的一个完整总结
2.最优化原理:
一个最优化策略具有这样的性质,不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。
3.子问题的重叠性:
子问题之间具有连续性,不独立存在;
2.个人理解
关于无后效性和子问题重叠性的理解:
比如说有一段路程是
该问题就是求A-B-C-D的最优解,这也是一个多阶段问题,可以拆分为A-B,B-C,C-D,且也是连续重叠的。
假定A-B2-C2-D是这道题的最优解,那么之前记录的A-B1-C1-D等路径数据不会对这条路径产生影响,这就是无后效性。
A-B,B-C之间有子问题的重叠,就是子问题的重叠性,子问题之间不单独存在(和分治法有区别),对于每个子问题只计算一次,记忆化,就会在解决子问题重叠性上面更快(动态规划就是计算并保存重叠子问题的解)(不会像递归一样大量重复计算);
关于最优化原理的理解:
例如学习数据结构的时候,构造最小生成树的方法来讲,不管是Prim算法还是Kruskal算法,都是从最小且不构成回路的边来选,只是在具体实施上有所区别;
四.动态规划的常见四种分类
1.线性动规:
- -线性动规
拦截导弹,合唱队形,挖地雷,建学校,剑客决斗等;
2.区域动规:
- -(区域动规待更新)
石子合并, 加分二叉树,统计单词个数,炮兵布阵等;
3.树形动规:
- -(树形动规待更新)
贪吃的九头龙,二分查找树,聚会的欢乐,数字三角形等;
4.背包问题:
- -背包问题
01背包问题,完全背包问题,分组背包问题,二维背包,装箱问题,挤牛奶(同济ACM第1132题)等
五.动态规划的基本思路
(1)确定状态
一般来说研究最优策略的最后一步,仔细观察,把大问题转化为子问题
(2)转移方程
转移方程可以看子问题的定义,是如何大问题化成子问题,是如何转移的来得到
(3)初始条件和边界情况
初始条件是什么?
初始条件是用转移方程算不出来的,需要手工定义的,然后基本上是能一眼看出来的;
边界情况就是注意类似于数组不要越界之类的
六.动态规划和贪心算法的区别
贪心算法简单介绍:
在对问题求解时,总是做出在当前看来是最好的选择。
在我才接触到贪心算法和动态规划的时候觉得他们两个没什么区别,都是做一个选择,从一个候选集合中选择适当的元素加入解集合;同时,贪心算法和动规都要求无后效性;
但是贪心算法是只考虑局部最优,而不考虑全局;
且贪心算法是每一步的最优解一定包含上一步的最优解,而动规是全局最优解中一定包含某个局部最优解,但不一定包含前一个局部最优解,因此需要记录之前的所有最优解。
因为动规是用空间换时间,对于大规模的问题如何在基本不影响运行速度的条件下,解决空间溢出的问题,是动态规划解决问题时一个普遍会遇到的问题,所以在能使用贪心算法的情况下就使用贪心算法。