专题三--动态规划总结

关于动态规划的粗浅认识

在这篇博客里我写一下做了一个月的dp之后对dp的粗浅认识,并附上一些学习资源。

最优子结构

如果一个问题的最优解包含其子问题的最优解,我们就称此问题具有最优子结构。 –摘自《算法导论》
也就是说,具有最优子结构的问题的最优解一定是由其各个子问题的最优解组合而成的。
我觉得dp最关键的就是找出状态转移方程,即找出问题的最优解与其子问题的最优解之间的关系。

设计动态规划算法的一般步骤
设计一个动态规划算法整体上分为两个步骤:


  1. 设计状态表达式
  2. 设计状态转移方程
    状态表达式 就是对我们所说的问题的一般描述。状态表达式的选择又取决于我们如何给这个问题划分求解的阶段,也就是为这个问题的每一个阶段,设计一个独一无二的表达式来表示他们,并且这个状态表达式的选择应该是满足无后效性的。
    状态转移方程 就是我们对一个问题如何由其子问题组成所做出的决策的一般描述。状态转移方程应该描述:

     

  1. 一个状态的解可以在哪些状态中选择
  2. 以何种条件在这些状态中选择出一个或多个,作为组成解状态的子状态
  3. 被选择出的一个或多个状态以何种方式组合起来,形成了当前状态的解

当这两个问题被解决了之后,一个动态规划算法的框架已经基本成型了。剩下的工作就是:

  1. 确定边界条件
  2. 计算时间和空间复杂度
  3. 判断是否满足题目要求,如果不满足应该如何优化,或者放弃这个思路

摘自ACM book

呃。。有种脱裤子放屁的赶脚。。其实就是寻找母问题分解为子问题的方式,然后按照此方式写出状态转移方程。将母问题分解为子问题的方式无疑是很关键的,这很大程度上决定了算法是否可行以及其复杂度。这就牵扯到了dp中的许多经典模型。

专题三中出现的dp模型

递推(直接找状态转移方程)

从前往后,分类枚举就行
题目:
1006 从上往下递推
1008 类似于数塔
1010 走台阶(Fibonacci数列)
1011 蜜蜂爬蜂房
1012 铺地砖
1013 母牛生小牛
1014 折线(有难度,可能因为我比较菜。。。)
1015 转化为二进制
1016 比较难想,不过也是递推

最大递增子序列

基础的状态转移方程为:F(k) = Max { F(i); 1<i < k 且 a[i] < a[k] } + 1
1001 模板题
1003 这道题着实挑战了我的英语水平
1005 这道题我觉得归类比较难,类似于DAG上的最长路,但也可以看做是LIS衍生而来吧,另外,一直对DAG上的动态规划与线性结构上的动态规划比较模糊,

最长公共子序列

1002 LCS的模板题

背包

这是这个专题里出现的模型中最难的了。
1006之后基本全是背包
背包最基础的是01背包,其他类型可以看作是01背包的变体。

需要注意的一点,动态规划还有一个重要的特征是将计算过的值存储起来,以空间换时间。
专题三中只是出现了几种基础的dp,而且已经告诉你这是dp,可我还是觉得有些吃力,基础太过薄弱是主要原因。递归与分治都没掌握好,dp当然会吃力。再回头从基础开始钻研吧。加油!少年!
https://www.zhihu.com/topic/19660018/hot
http://janfan.github.io/chinese/2015/01/21/dynamic-programming.html
http://love-oriented.com/pack/pack2alpha1.pdf





posted @ 2016-05-31 22:15  Pic  阅读(289)  评论(0编辑  收藏  举报