`

基本动态规划讲解

 
阅读更多

动态规划

动态规划

算法总体思想

动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题

但是经分解得到的子问题往往不是互相独立的。不同子问题的数目常常只有多项式量级。在用分治法求解时,有些子问题被重复计算了许多次。

如果能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,就可以避免大量重复计算,从而得到多项式时间算法。

动态规划基本步骤:

(1)找出最优解的性质,并刻划其结构特征。

(2)递归地定义最优值。

(3)以自底向上的方式计算出最优值。

(4)根据计算最优值时得到的信息,构造最优解。

实例一、完全加括号的矩阵连乘积

问题可递归定义:

(1)单个矩阵是完全加括号的;

(2)矩阵连乘积A是完全加括号的 ,则A可表示为2个完全加括号的矩阵连乘积B和C的乘积并加括号,即 A = (BC)。

设有四个矩阵A,B,C,D它们的维数分别是: A = 50*10 , B = 10*40 , C = 40*30 , D = 30*5

总共有五中完全加括号的方式:

 

例如:((A(BC))D): 10 * 40 * 30 + 10 * 30 * 50 + 50 * 30 * 5 = 34500

给定矩阵{A1, A2, A3,..., An},其中Ai与A(i+1)是可乘的。i = 1,2,3, ..., n - 1。考察这n个矩阵的连乘积A1*A2*A3...An.

由于矩阵乘法满足结合律,所以计算矩阵的连乘可以有许多不同的计算次序。这种计算次序可以用加括号的方式来确定。

若一个矩阵连乘积的计算次序完全确定,也就是说该连乘积已完全加括号,则可以依此次序反复调用2个矩阵相乘的标准算法计算出矩阵连乘积。

矩阵连乘问题

给定矩阵{A1, A2, A3,..., An},其中Ai与A(i+1)是可乘的。i = 1,2,3, ..., n - 1。考察这n个矩阵的连乘积A1*A2*A3...An. 如何确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少.

穷举法:列举出所有可能的计算次序,并计算出每一种计算次序相应需要的数乘次数,从中找出一种数乘次数最少的计算次序。

算法复杂度分析:

对于n个矩阵的连乘积,设其不同的计算次序为P(n)

由于每种加括号方式都可以分解为两个子矩阵的加括号问题

(A1...Ak)(A(k+1)…An)可以得到关于P(n)的递推式如下:

动态规划:将矩阵连乘积A(i)A(i+1)…A(j)简记为A[i:j],这里 i <= j。

考察计算A[i:j]的最优计算次序。设这个计算次序在矩阵A(k)和A(k+1)之间将矩阵链断开,i <= k < j, 则其相应完全加括号方式为(A(i)A(i+1)...A(k)) * (A(k+1)A(k+2)...A(j))。

计算量:A[i:k]的计算量加上A[k+1,j],再加上A[i:k] * A[k+1][j]的计算量。

分析最优解的结构

特征:计算A[i:j]的最优次序所包含的计算矩阵子链 A[i:k]和A[k+1:j]的次序也是最优的。

矩阵连乘计算次序问题的最优解包含着其子问题的最优解。这种性质称为最优子结构性质。问题的最优子结构性质是该问题可用动态规划算法求解的显著特征。

建立递归关系

设计算A[i:j],1 <= i <= j <= n,所需要的最少数乘次数m[i,j],则原问题的最优值为m[1,n]

当i = j时,A[i:j]=Ai,因此,m[i,i] = 0,i = 1,2,…,n

当i < j时,m[i,j] = m[i,k] + m[k+1,j] + p(i-1)p(k)p(j)

这里A(i)的维数为p(i-1)*(i)(注:p(i-1)为矩阵A(i)的行数,p(i)为矩阵A[i]的列数)

可以递归地定义m[i,j]为:

k的位置只有j - i种。

计算最优值

对于1 <= i <= j <= n不同的有序对(i,j)对应于不同的子问题。因此,不同子问题的个数最多只有:

(大括号表示C(n,2),组合的意思。后面的符号表示 “紧渐近界记号”)

但是,在递归计算时,许多子问题被重复计算多次。这也是该问题可用动态规划算法求解的又一显著特征。

用动态规划算法解此问题,可依据其递归式以自底向上的方式进行计算。在计算过程中,保存已解决的子问题答案。每个子问题只计算一次,而在后面需要时只要简单查一下,从而避免大量的重复计算,最终得到多项式时间的算法。

用动态规划法求最优解

连乘矩阵假如为:

计算过程为:

从m可知最小连乘次数为m[1][6] = 15125

从s可知计算顺序为((A1(A2A3))((A4A5))A6))

实现:

 

代码

 

 

算法复杂度分析:

算法matrixChain的主要计算量取决于算法中对r,i和k的3重循环。循环体内的计算量为O(1),而3重循环的总次数为O(n^3)。因此算法的计算时间上界为O(n^3)。算法所占用的空间显然为O(n^2)。

动态规划算法的基本要素

一、最优子结构

矩阵连乘计算次序问题的最优解包含着其子问题的最优解。这种性质称为最优子结构性质。

在分析问题的最优子结构性质时,所用的方法具有普遍性:首先假设由问题的最优解导出的子问题的解不是最优的,然后再设法说明在这个假设下可构造出比原问题最优解更好的解,从而导致矛盾。

利用问题的最优子结构性质,以自底向上的方式递归地从子问题的最优解逐步构造出整个问题的最优解。最优子结构是问题能用动态规划算法求解的前提。

同一个问题可以有多种方式刻划它的最优子结构,有些表示方法的求解速度更快(空间占用小,问题的维度低)

二、重叠子问题

递归算法求解问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次。这种性质称为子问题的重叠性质

动态规划算法,对每一个子问题只解一次,而后将其解保存在一个表格中,当再次需要解此子问题时,只是简单地用常数时间查看一下结果。

通常不同的子问题个数随问题的大小呈多项式增长。因此用动态规划算法只需要多项式时间,从而获得较高的解题效率。

三、备忘录方法

备忘录方法的控制结构与直接递归方法的控制结构相同,区别在于备忘录方法为每个解过的子问题建立了备忘录以备需要时查看,避免了相同子问题的重复求解。

实现(见矩阵连乘源码)

实例二、最长公共子序列

若给定的序列X = {x1,x2,…,xm},则另一序列Z = {z1,z2,…,zk},是X的子序列是指存在一个严格下表序列{i1,i2,…,ik}使得对于所有的j = 1,2,…k有zj = xij。例如,序列Z = {B,C,D,B}是序列X = {A,B,C,B,D,A,B}的子序列,相应的递增下标序列为{2,3,5,7}。

给定2个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列

问题表述:给定2个序列X={x1,x2,…,xm}和Y = {y1,y2,…,yn},找出X和Y的最长公共子序列。

最长公共子序列的结构

设序列X = {x1,x2,…,xm}和Y = {y1,y2,…,yn}的最长公共子序列为Z = {z1,z2,…,zk} ,则

(1)若xm = yn,则zk = xm = yn,且z(k-1)是x(m-1)和y(n-1)的最长公共子序列。

(2)若xm != yn且zk != xm,则Z是x(m-1)和Y的最长公共子序列。

(3)若xm != yn且zk != yn,则Z是X和y(n-1)的最长公共子序列。

由此可见,2个序列的最长公共子序列包含了这2个序列的前缀的最长公共子序列。因此,最长公共子序列问题具有最优子结构性质

子问题的递归结构

由最长公共子序列问题的最优子结构性质建立子问题最优值的递归关系。用c[i][j]记录序列Xi和Yi的最长公共子序列的长度。其中, Xi={x1,x2,…,xi};Yj={y1,y2,…,yj}。当i = 0或j = 0时,空序列是Xi和Yj的最长公共子序列。故此时C[i][j] = 0。其它情况下,由最优子结构性质可建立递归关系如下:

由于在所考虑的子问题空间中,总共有θ(mn)个不同的子问题,因此,用动态规划算法自底向上地计算最优值能提高算法的效率

计算最优值和构造最长公共子序列(见源码)

实现:

 
代码

 

 

算法的改进

在算法lcsLength和lcs中,可进一步将数组b省去。事实上,数组元素c[i][j]的值仅由c[i-1][j-1],c[i-1][j]和c[i][j-1]这3个数组元素的值所确定。对于给定的数组元素c[i][j],可以不借助于数组b而仅借助于c本身在时间内确定c[i][j]的值是由c[i-1][j-1],c[i-1][j]和c[i][j-1]中哪一个值所确定的。

如果只需要计算最长公共子序列的长度,则算法的空间需求可大大减少。事实上,在计算c[i][j]时,只用到数组c的第i行和第i-1行。因此,用2行的数组空间就可以计算出最长公共子序列的长度。进一步的分析还可将空间需求减至O(min(m,n))。

实例三、最大子段和

问题表述

n个数(可能是负数)组成的序列a1,a2,…an.求该序列

例如: 序列(-2,11,-4,13,-5,-2) ,最大子段和:

11 - 4 + 13=20。

(1)穷举算法: O(n3), O(n2)

(2)分治法:

将序列a[1:n]从n/2处截成两段:a[1:n/2], a[n/2+1:n]

实例三、最大子段和

问题表述

n个数(可能是负数)组成的序列a1,a2,…an.求该序列子序列的最大值。

也就是

 

例如: 序列(-2,11,-4,13,-5,-2) ,最大子段和:

11 - 4 + 13=20。

(1)穷举算法: O(n3), O(n2)

(2)分治法:

将序列a[1:n]从n/2处截成两段:a[1:n/2], a[n/2+1:n]

一共存在三种情况:

a.最大子段和出现在左边一段

b.最大子段和出现在右边一段

c.最大子段和跨越中间的断点

对于前两种情况,只需继续递归调用,而对于第三种情况:

那么S1+S2是第三种情况的最优值。

(3)动态规划法:

定义b[j]:

含义:从元素i开始,到元素j为止的所有的元素构成的子段有多个,这些子段中的子段和最大的那个。

那么:

如果:b[j-1] > 0, 那么b[j] = b[j-1] + a[j]

如果:b[j-1] <= 0,那么b[j] = a[j]

这样,显然,我们要求的最大子段和,是b[j]数组中最大的那个元素。

实现:

 
代码

 

 

实例四、多边形游戏

多边形游戏是一个单人玩的游戏,开始时有一个由n个顶点构成的多边形。每个顶点被赋予一个整数值,每条边被赋予一个运算符”+”或”*”。所有边依次用整数从1到n编号。

游戏第1步,将一条边删除。

随后n-1步按以下方式操作:

(1)选择一条边E以及由E连接着的2个顶点V1和V2;

(2)用一个新的顶点取代边E以及由E连接着的2个顶点V1和V2。将由顶点V1和V2的整数值通过边E上的运算得到的结果赋予新顶点。

最后,所有边都被删除,游戏结束。游戏的得分就是所剩顶点上的整数值。

问题:对于给定的多边形,计算最高得分。

最优子结构性质

按照顺时针顺序,多边形和顶点的顺序可以写成:

op[1], v[1], op[2], v[2],…, op[n], v[n]

在所给多边形中,从顶点i(1 <= i <= n)开始,长度为j(链中有j个顶点)的顺时针链p(i,j)可表示为

v[i], op[i+1], v[i+1],…, op[i+j-1], v[i+j-1]

如果这条链在op[i + s]处进行最后一次合并运算(1 <= s <= j-1),则可在op[i+s]处将链分割为2个子链:

从i开始长度为s的链:p(i,s)

从i + s开始,长度为j - s的链:p(i + s,j-s)。

设:

m1是对子链p(i,s)的任意一种合并方式得到的值,而a和b分别是在所有可能的合并中得到的最小值和最大值。

m2是p(i+s,j-s)的任意一种合并方式得到的值,而c和d分别是在所有可能的合并中得到的最小值和最大值。

依此定义有a <= m1 <= b,c <= m2 <= d

(1)当op[i+s] = ‘+’时,显然有a + c <= m <= b + d

(2)当op[i+s] = ’*’时,有

min {ac,ad,bc,bd} <= m <= max {ac,ad,bc,bd}

换句话说,主链的最大值和最小值可由子链的最大值和最小值得到

实现:

 

 

代码

 

分享到:
评论

相关推荐

    背包问题九讲(非常不错的动态规划讲解,搞ACM必备)

    本篇文章是我(dd_engi)正在进行中的一个雄心勃勃的写作计划的一部分,这个计划的内容是写作一份较为完善的NOIP难度的动态规划总结,名为《解动态规划题的基本思考方式》。现在你看到的是这个写作计划最先发布的一...

    动态规划算法思想及其步骤

    对动态规划有着比较详细的讲解,比如动态规划的一般步骤,动态规划的思想

    经典动态规划问题举例详解

    对于动态规划,每个刚接触的人都需要一段时间来理解,特别是第一次接触的时候总是想不通为什么这种方法可行,这篇文章就是为了帮助大家理解动态规划,并通过讲解基本的01背包问题来引导读者如何去思考动态规划。...

    动态规划基础(初学者必读)

    详细的讲解了动态规划基本思想,基本步骤,内附经典例题!(包括经典的背包问题,初学者必看)!前提 ●贪心法(它是一种多步决策法,它总是作出在当前看来是最好的选择,它的考虑不是从整体出发,而只是某种意义上...

    常规动态规划算法的讲义

    介绍动态规划的一些基本的形式,以及对一些在线测试的系统的动态规划试题的讲解

    动态规划一

    通为什么这种方法可行,这篇文章就是为了帮助大家理解动态规划,并通过讲解基本的01 背包问题来引导读者如何去思考动态规划。本文力求通俗易懂,无异性,不让读者感到迷惑, 引导读者去思考,所以如果你在阅读中发现...

    动态规划的ppt

    该ppt讲解了算法导论的第十五章动态规划部分。主要讲述了1.动态规划与分治的区别;2. 通过三个例子棍子切割问题、矩阵链相乘问题和最长公共子序列问题详细描述了动态规划的基本步骤;3.最后做了一个最长单调递增子...

    动态规划讲义(非原创)

    动态规划的一些基本问题讲解,还有一些经典的模型

    dp算法思想及运用实践例题

    主要讲解了动态规划的基本思路步骤和相关例题,以便更好的理解动态规划的初级运用和实践。动态规划算法的有效性依赖于待求解问题本身具有的两个重要性质:最优子结构性质和子问题重叠性质。 1、最优子结构性质。如果...

    数学建模算法大全及例题讲解

    第01章 线性规划.pdf 第02章 整数规划.pdf ...第04章 动态规划.pdf 第05章 图与网络.pdf ... 第22章 模糊数学模型.pdf ... 第30章 偏最小二乘回归.pdf 共三十章,丰富的例题讲解,包含数学建模基本上所有的算法。

    各种基本算法的课件 英文版 中南大学

    讲解各种基本算法的课件 蛮力 递归 动态规划等 英文版 中南大学

    dp.rar_DP

    这是针对于 初学动态规划的程序员所设计的一套讲义。它深入浅出的讲解了动态规划的基本原理及其推广

    尚硅谷老韩java版算法和数据结构讲解代码笔记整理.zip

    算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),图论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法...

    北京大学2011年acm暑期培训课件

    2) 动态规划:状态压缩,树形动归,平行四边形法则 3) 数据结构(二): DFA, Trie树,Trie图等 4) 搜索:深搜,广搜,剪枝,IDA*算法 源代码 5) 若干图论问题:最小生成树 强连通分量、桥和割点等 6) 计算几何:线与...

    数据结构与排序算法------通过代码示例,讲解:数据结构和9种排序算法。.zip

    算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),图论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法...

    通过Dreamweaver CS3学习HTML+DIV+CSS

    动态网站篇——讲解网页脚本技术的应用、基于动态页面的ASP网站实现;Web 2.0网站篇——演示Web 2.0标准网站的设计过程。 本书既适合入门级的初学者、网站管理维护人员和大专院校学生,也可供中级设计人员参考。

    【零基础学算法】 超详细动画讲解支持 Java, C++, Python, Go, JS, TS, C#, Swift等语言)

    算法:搜索、排序、分治、回溯、动态规划、贪心等算法的定义、优缺点、效率、应用场景、解题步骤、示例题目等。 相较于文字,视频和图片具有更高的信息密度和结构化程度,更易于理解。在本书中,重点和难点知识将...

    VMProtect的逆向分析和静态还原

    详细介绍了VMProtect的特点,同时讲解了vmp的逆向分析和静态还原点。...(五)转换汇编指令——动态规划 (六)寄存器染色 基本块内的寄存器轮转 基本块间的寄存器轮转 寄存器的二义性问题 识别寄存器的二义性的步骤

    《图解数据结构与算法》正文试读页

    然后通过例子来讲解递归和动态规划的算法思想;接着对树进行了详细的讲解,包括二叉树、AVL树和红黑树等;最后介绍了一些高级的数据结构和算法,如哈希表、Bloom Filter和图论等。 这本书采用“少字多图”的方式,...

    北京大学ACM暑期课课件

    课程内容共八个专题,除理论知识外还包括精选例题讲解 7.8 数据结构(一): 线段树,树状数组,二维线段树 7.9 数据结构(二): 并查集, DFA, Trie树,Trie图等 7.10 搜索:深搜,广搜,...7.18 最小生成树和动态规划

Global site tag (gtag.js) - Google Analytics