当前课程知识点:数据结构(上) > 第一章 绪论(下) > (xc)动态规划 > 01XC-A: LCS:动态规划
稍加对比不难发现
我们这里所处的困境
与最初Fibonacci数的递归算法
颇为类似
具体来讲
这里也有大量重复的递归实例
也就是对应的子问题
而且在最坏情况下
它确实会出现指数这么多个
而反过来 这里头的每一个子问题
正像我们刚才那个表那样
其实都唯一的对应于A B各自
某一个前缀共同的一个组合
因此它们总数就像
那个表格里头的单元数一样
累计也不过就是 n乘以m
是乘法这么多种
因此我们完全可以采用
或者叫套用
刚才改进Fibonacci数算法的
那种动态规划的策略
具体来说 也就是将
计算的方向颠倒过来
并且把计算的形式
从刚才貌似简明的递归
改为“似拙实巧”的迭代
我们可以在同样的这张表上
进行新的计算
具体地 这里同样是把相应的
那一对序列 分别作为行和列
然后呢 对这个表做一个初始化
也就是分别给出
第0行和第0列
我们接下来的工作呢
就是逐行逐列地填写这张表
如何填写呢?
看一下
就是按照这样的一个次序
具体来说
对于其中的任何一个单元
我们都要根据它
到底是减而治之
还是分而治之 来做处理
如果是减而治之
像刚才这个情况
因为a和a是相同的
那么我们就直接取它
左上角的这个单元
简明地加个1就可以了
大家需要确认的是
每次碰到这种情况的时候
所对应的左上角这个元素
都是必然存在的
所以这种计算是安全的
我们再来看分而治之的情况
比如说 还是这个T
和这里的C
所对应的这个情况
因为这个时候T和C不等
所以它会分别地
去取它的上方的这个单元
也就是它对应的那个子问题
以及左侧的这个单元
所对应的子问题
将它们的解分别取出来
并且将它们中的
更大者保留下来
同样我们这里要确认一下
按照我们初始化的原则
和计算的方向和次序约定
每一个这样的情况出现的时候
上方和左侧两个单元格
所对应的子问题
都已经计算并且得到了结果
所以这种取法同样是安全的
总而言之
只要做刚才那样的一个初始化
然后按照适当的 比如说从行
然后接着再到列的计算次序
总能够保证这个表中的各项
可以按照刚才的
那样的一个原则
安全地、准确地计算出来
而整个这样的一个计算过程
是我们最初向上
和向左的计算过程的
逆向的一个过程
而更重要的是 对于其中的
任何一个子问题
都只需要计算一次
而不是很多次
所以这样一个颠倒次序以后的
迭代式的计算过程
复杂度就应该恰好等于
这张表格的规模
也就是它的行乘以它的列
n乘以m 而不是2的n次方
或者是m次方
总结一下
递归虽然可以帮助我们很好地
找到一个可行并且正确的解
但是 如果要将效率提高
使之变成一个实用算法的话
我们往往还需要进行
进一步的调试
而在这个过程中
动态规划扮演着
非常重要的角色
这也是这一节
希望大家重点掌握的内容
-选课之前
--写在选课之前
--宣传片
-考核方式
--考核方式
-OJ系统说明
--关于OJ
--1-注册与登录
--2-界面与选课
--3-提交测试
-关于课程教材与讲义
--课程教材与讲义
-关于讨论区
--关于讨论区
-微信平台
--html
-PA晋级申请
--PA晋级
-(a)计算
--演示
--(a)计算--作业
-(b)计算模型
-(b)计算模型--作业
-(c)大O记号
-(c)大O记号--作业
-(d)算法分析
-(d)算法分析--作业
-(e)迭代与递归
-(e)迭代与递归--作业
-(xc)动态规划
-- 演示
-(xc)动态规划--作业
-本章测验--作业
-(a)接口与实现
--02A-5 复制
-(a)接口与实现--作业
-(b)可扩充向量
-(b)可扩充向量--作业
-(c)无序向量
--02C-1 概述
--02C-3 插入
--02C-6 查找
--02C-8 遍历
-(c)无序向量--作业
-(d1)有序向量:唯一化
-(d1)有序向量:唯一化--作业
-(d2)有序向量:二分查找
-(d2)有序向量:二分查找--作业
-(d3)有序向量:Fibonacci查找
-(d3)有序向量:Fibonacci查找--作业
-(d4)有序向量:二分查找(改进)
-(d4)有序向量:二分查找(改进)--作业
-(d5)有序向量:插值查找
-第二章 向量(下)--(d5)有序向量:插值查找
-(e)起泡排序
--02E-2 改进
--02E-3 反例
-(e)起泡排序--作业
-(f)归并排序
-(f)归并排序--作业
-本章测验--作业
-(a)接口与实现
--03A-4 实现
-(a)接口与实现--作业
-(b)无序列表
--03B-2 查找
-(b)无序列表--作业
-(c)有序列表
--03C-3 查找
-(c)有序列表--作业
-(d)选择排序
--03D-1 构思
--03D-2 实例
--03D-3 实现
--03D-4 推敲
--03D-6 性能
-(d)选择排序--作业
-(e)插入排序
--03E-1 经验
--03E-2 构思
--03E-3 对比
--03E-4 实例
--03E-5 实现
-(e)插入排序--作业
-(xd)习题辅导:LightHouse
-本章测验--作业
- (a)栈接口与实现
--04A-1 栈
--04A-2 实例
--04A-3 实现
- (a)栈接口与实现--作业
-(c1)栈应用:进制转换
-第四章 栈与队列--(c1)栈应用:进制转换
-(c2)栈应用:括号匹配
-(c2)栈应用:括号匹配--作业
-(c3)栈应用:栈混洗
-第四章 栈与队列--(c3)栈应用:栈混洗
-(c4)栈应用:中缀表达式求值
-(c4)栈应用:中缀表达式求值--作业
-(c5)栈应用:逆波兰表达式
-第四章 栈与队列--(c5)栈应用:逆波兰表达式
-(d)队列接口与实现
--04D-1 接口
--04D-2 实例
--04D-3 实现
-第四章 栈与队列--本章测验
-(a)树
--05A-1 动机
--05A-2 应用
-(a)树--作业
-(b)树的表示
--05B-2 父亲
--05B-3 孩子
-第五章 二叉树--(b)树的表示
-(c)二叉树
-(c)二叉树--作业
-(d)二叉树实现
-(d)二叉树实现--作业
-(e1)先序遍历
-(e1)先序遍历--作业
-(e2)中序遍历
-第五章 二叉树--(e2)中序遍历
-(e4)层次遍历
-第五章 二叉树--(e4)层次遍历
-(e5)重构
-(e5)重构--作业
-本章测验--作业
-(a)概述
-(a)概述--作业
-(b1)邻接矩阵
-(b1)邻接矩阵--作业
-(c)广度优先搜索
--06C-2 策略
--06C-3 实现
--06C-5 实例
-(c)广度优先搜索--作业
-(d)深度优先搜索
--06D-1 算法
--06D-2 框架
--06D-3 细节
-(d)深度优先搜索--作业
-第六章 图--本章测验