动态规划总结
来源:互联网 发布:印刷厂计件软件 编辑:程序博客网 时间:2024/05/16 14:37
学习动态规划有一段时间了,总结一下,开始新的算法
一、为什么要使用动态规划?
当回溯效率太低的时候,动态规划是个不错的选择,因为它是不断建立在最优状态上的递推,得出最终结果。
二、动态规划两大标志:
1)最优子结构:一个问题的最优解包含子问题的最优解,这个性质被称为最优子结构
2)重叠子问题:不同问题包含相同的子问题。即:原问题不断分解成同样的子问题,而不是产生新的问题。
重点:重叠子问题和子问题独立性的区别:首先来举个例子:图中有a、b、c、d四个顶点,他们之间存在若干条路径,求从a到d的最短路径,这个可以使用动态规划来实现。但如果求从a到b的最长路径,则不能使用动态规划,因为设存在a--->b--->d,所以原问题分解成a--->b和b--->d的两个子问题。而对于a--->b子问题中可能会包含d节点,这回影响b--->d这个子问题的结果。大家明白了吧,子问题独立性要求是:对于同一个问题的子问题相互独立。这就是与重叠子问题的区别,重叠子问题是相对于不同问题的子问题的。至于最长路径问题好像用到什么NP完全性(难道就是集合上的动态规划?!),暂时还不理解。
三:动态规划解题关键:
通过分析数据,找到状态,然后找到其中的状态转移方程,然后问题解决。
具体实现有两种方法:
1)记忆化搜索:简便、而且思路会很清晰。针对性计算,这是递归的主要好处,从顶到底。
2)递推:无需递归的代价,但可能会计算一些不必要的值,从底到顶。
四:主要题型:
1)DAG模型(即有向无环图),如:最长最短路径问题
2)多阶段决策问题,如:0-1背包问题,最优矩阵,最长公共子序列,最优搜索二叉树
3)集合上的动态规划(状态压缩):如:状态中涉及到“除了一些点之外”类问题,和棋盘和网格中的某些问题(一行一行进行递推)
做题时的一些小技巧:如果要求输出字典序最小的,状态转移最好从前向后进行递推。
位运算的运算级比较低,所以应多用括号。
五:动态规划的效率?
依赖于子问题的个数和每一个子问题中有多少的选择,两者的乘积即为算法的效率。
小小的感悟:永远不要认为你这道题没有做过,做不出来,从题中给出的数据开始,硬是找出两个状态寻找它们之间的联系,用笔画到本上,思路就会出来了。关键是找到状态转移方程。其中用到的一个小技巧,但是一般不会注意到就是:开始可以假设一个状态已知,然后开始分析,向前或者向后都可以。“剪贴”来确保你找到的是最优解,这个证明的时候会用到,但是解题的时候很少用。
OK了,参见:《算法导论》《算法导论入门经典》
六、补充:
1、专题训练动态规划总结:
①动态转移方程中两种形式,d[i][j],一种是必包含第i状态,一种是前j个状态。poj1024中利用前者,优化算法。
②临界状态处理,如果简单处理不可以,则使用if语句判定,结合使用。
③滚动数组中的空间和时间优化。poj1024
④尽量少使用递归。
2、01背包的几种情况
①求最大价值,包不必放满,初始化:memset(d, 0, sizeof(d));
②求最小价值,包不必放满,初始化:
for j = 1...N
d[j] = INF;
d[0] = 0;
③求最大价值,包必须放满,初始化:
for j = 1...N
d[j] = -INF;
d[0] = 0;
3、树形DP
把根的所有子节点看作很多层,选择该子树,或者不选择,于是就可以转变为01背包问题,只是需要在更新前,首先需要对子树更新完成。递归实现即可。
一般,使用d[i]表示以i节点为根节点,并必然包含i节点,会更好处理问题。
- 动态规划总结
- 动态规划总结
- 【转】动态规划总结
- 动态规划总结
- 动态规划总结
- 动态规划总结
- noip动态规划总结
- 动态规划总结
- 动态规划总结
- 动态规划总结
- 动态规划原理总结
- 动态规划总结
- 动态规划总结
- 动态规划总结
- 动态规划总结
- 动态规划算法总结
- 简单动态规划总结
- 动态规划总结
- windows 2003 SOCKET 端口数量默认5000
- 视频跟踪算法简介
- NAND Flash的坏块管理设计
- Java中的volatile关键字
- STL map, STL set之数据结构基础
- 动态规划总结
- 2-4摇篮曲
- mysql 乱码
- 蓝屏代码——STOP:c000021a Unknown Hard Error
- Linux内核中NAND Flash坏块管理
- 数据库中增删改查
- Lua在 linux下源码编译问题之readline/readline.h:没有那个文件或目录解决方法
- 随想录(linux的四个维度)
- 事件冒泡