Dynamic Programming (动态规划问题)

 动态规划定义:

我们在运用分治原理解决问题时,会将问题分成好几个子问题进行递归地求解;然而存在这样一个问题:如果子问题并非相互独立的,运用分治原理将重复地计算公共的子问题,浪费许多时间

在解决一类特殊的问题——优化问题时,我们引入特殊的动态规划方法进行求解,通常无需重复计算子问题。

 

 自底向上地求解子问题:从问题的边界条件入手向上计算。

 使用动态规划的条件:具有优化子结构;子问题部分重叠。说到底还是一种特殊的分治递归,只不过为了不重复计算所以将问题的解列表存储调用。

优化子结构:当一个问题的优化解包含了子问题的优化解时,我们说这个问题具有优化子结构。为了能解决多阶段决策的最优性必须能满足这个性质。

 矩阵链乘法问题:

 在矩阵乘法操作中,元素乘法的操作次数远大于元素加法,因此我们将元素乘法作为基本操作分析算法复杂性。

乘法代价为O(q*r(一行p个元素r列)*p(一共p行))

 观察代价的结构,算出子代价之后还有一个Merge的代价。从Ai断开的,merge代价为P0PiPn。

 

 利用这j-i对就可以计算出m[i,j]

 

 从最外层对角线向上计算。

 最长公共序列问题:

子序列是在原序列中不回头地任取的,并不要求连续取。

 

 当xm≠yn时可直接使用这个取max的等式找出LCSxy,不需要另行判断。(在取max过程中其实已经判断了)

 注意:xm不一定和ym在公共子序列里配对,X和Y的长度未知。但是不妨碍xm一定是LCS的最后一个元素。

 要验证具有优化子结构,说明根问题的优化解中包含子问题的优化解。运用反证法证明Zk-1是Xm-1和Yn-1的LCS,证明思路和证明矩阵链乘法的优化解包含两个子问题的优化解那个思路是一样的,如果子问题并不是优化解,我们可以另选优化解出来使得根问题的优化解也不成立。

由于zk≠xm,那么首先LCSxy要从Xm-1和Y中选,是它俩的公共子序列。往证是它俩的最长CS。还是运用反证法,如果存在一个更长的那么依旧可以更新根问题的优化解。

 构造最优解的时候最多也就是把两条边全走完,所以直接O(m+n)。

 0/1背包问题:

 建立优化解代价的递归方程:

 0≤j<wn指本次装包容量不够了装不下。反之就是尚有空余。

递归地划分子问题:

当C<<2^n时,直接计算nC个格子就好,有许多重复的子问题。 

自底向上计算优化解的代价记录优化解的构造信息:

 最后一行为边界条件,值为vn/0;第一列全为0,由此完善整个表;

m[i,j]中i、j作为两个限制条件分别用一个循环去表示。

 表格更新完之后再计算m[1,C]。

因为ωi与C都设为整数,代价的递归方程是以ωi分界的;那么就有两种情况,ωi<=C,也即ωi-1<C,此时整个表将按上图代码更新。

另一种情况为部分ωi>C(这是完全有可能的),此时我们需要对每一个ωi与C的大小进行判断,如果wi>C,那么xi必定等于0(根本放不进去~)

我们用下图代码完成更准确的判断,使用min函数每次花θ(1)的时间。

 构造优化解:

 还有一类部分背包问题,指的是要装载的东西可以分割比如沙子和矿石,这时我们就挑选质价比最高的东西装就好了。

二分优化搜索树:

 

 最小化整棵树的期望搜索代价。

优化解的结构分析:

 先声明这样两棵树:二叉搜索树T的根节点为kr,由关键字集合{k1,k2,……,kn}构成;其子树根节点为kl,子树由关键字集合{ki,ki+1,……,kj}构成。我们证明的主要思路依然是通过更新部分的优化解来否定总体的优化解从而导出矛盾。

 这样当我们找到一个平均查找期望更小的子树T”时就可以更新总代价了。这一点往回想很有意思,我们说“找到一个平均查找期望更小的子树T” ”其实指的是找到关键字集{ki,ki+1,……,kj}的另一种排列方式,而子树的根节点与所有节点构成的树的根节点的“距离”是不变的。所以后面这个加和项其实是一个与排列方式无关的常量捏。

以及这里的E(T’)并不表示T‘本身的查找期望代价,而是T’中的点对T这棵树的期望搜索代价的贡献,是站在T的视角看的。

我们是否能使用真正的期望来做优化子结构的分析呢?答案是肯定的:将贡献的期望换为真正的期望,我们要改动的无非是各个点的查找概率(进行规格化),看起来会给整个算式加上复杂的系数,但是!对于整个树的代价等于PL*E(左子树)+Eroot+PR*E(右子树),而PL、PR就是规格化的底数,完全消掉了~期望相减得出来和上图是一样的。

重复子问题:都需要计算k3k4/k1k2/k2k3这棵子树的最优解

建立优化解代价的递归方程:

 

 

 Pi被W(i,j)吸收了。

 递归地划分子问题:

 类同计算矩阵链乘法的那个题。

自底向上计算优化解的代价 记录优化解的构造信息:

 

 

 与其说是三层循环每层至多n步。不如说是n个O(n²)。可以取循环的起点和终点看看。

 构造优化解:

 

 

 最小编辑距离:

 

 优化解结构信息:

 

 

 个人更喜欢上图对优化子结构的解释。

 还是一样的反证。

 建立代价的递归方程:

 递归划分子问题、自底向上求解子问题:

  

 

 

 构造优化解:

 E[i,j]当i或j等于0时本无意义(按照图片中对数组的设定),不如按照我手写的那张来弄。

 最小编辑距离判别问题:

 多段图规划:

 子集求和问题:

 

 加上布尔代数来证明一个定理。

 

最长增长子序列问题:

思路:令dp[i]表示以A[i]作为结尾的最长增长子序列的长度。于是,通过设置这样一个数组,最长增长子序列的长度就是数组dp中的最大值。

由于dp[i]是以A[i]作为末尾的最长递增子序列,因此只有两种情况:Ai之前的元素都比Ai大,即最长增长子序列只有Ai本身,dpi=1;

或Ai之前的元组Aj比Ai小,此时只需将Ai添加到Aj作为末尾的最长增长子序列便可构成一个新的递增子序列,即dpi=dpj+1.只需将i之前的元素逐一遍历,便可以得到以Ai作为结尾的最长增长子序列的长度dpi。

从而可以得到状态转移方程 dpi=max{1,dpj+1|j<i&&Aj<Ai}。

1.直接使用递归来做:

参考 http://t.csdn.cn/mw66Z

O(2^n)

2.DP

 图中存在大量重叠子问题。

 首先我们可以初始化 dp[] 中的元素均为 1,因为以数组 arr[] 中的任意一个元素结尾的最长递增子序列的长度至少为 1 (即自身,这就相当于假设数组仅包含一个元素,长度自然为 1,也是递归的出口),再根据递归方程逐步更新

状态转移方程:

 

 O(n^2)

3.DP+BS

O(nlogn)

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值