动态规划
- 格式:doc
- 大小:33.50 KB
- 文档页数:6
第6章 动态规划动态规划(Dynamic Programming )是解决多阶段决策过程最优化的一种有用的数学方法。
它是由美国学者Richard .Bellman 在1951年提出的,1957年他的专著《动态规划》一书问世,标志着运筹学的一个重要分支-动态规划的诞生.动态规划也是一种将多变量问题转化为单变量问题的一种方法。
在动态规划中,把困难的多阶段决策问题变换成一系列相互联系的比较容易的单阶段问题一个个地求解。
动态规划是考察解决问题的一种途径 ,而不是一种特殊的算法,不像线性规划那样有统一的数学模型和算法(如单纯形法).事实上,在运用其解决问题的过程中还需要运用其它的优化算法。
因此,动态规划不像其它方法局限于解决某一类问题,它可以解决各类多阶段决策问题。
动态规划在工程技术、经济管理等社会各个领域都有着广泛的应用,并且获得了显著的效果。
在经济管理方面,动态规划可以用来解决最优路径问题、资源分配问题、生产调度问题、库存管理问题、排序问题、设备更新问题以及生产过程最优控制问题等,是经济管理中一种重要的决策技术。
许多规划问题用动态规划的方法来处理,常比线性规划或非线性规划更有效。
特别是对于离散的问题,由于解析数学无法发挥作用,动态规划便成为了一种非常有用的工具。
动态规划可以按照决策过程的演变是否确定分为确定性动态规划和随机性动态规划;也可以按照决策变量的取值是否连续分为连续性动态规划和离散性动态规划。
本教材主要介绍动态规划的基本概念、理论和方法,并通过典型的案例说明这些理论和方法的应用。
6.1动态规划的基本理论6.1.1多阶段决策过程的数学描述有这样一类活动过程,其整个过程可分为若干相互联系的阶段,每一阶段都要作出相应的决策,以使整个过程达到最佳的活动效果。
任何一个阶段(stage ,即决策点)都是由输入(input )、决策(decision )、状态转移律(transformation function )和输出(output )构成的,如图6-1(a )所示.其中输入和输出也称为状态(state ),输入称为输入状态,输出称为输出状态。
什么是动态规划?⼀、基本思想态规划算法的基本思想与分治法类似,都是将问题⼤问题拆分为⼩问题,通过⼩问题的求解来得到最后的解。
与分治法不同的是,分治法是分⽽治之,分治法将⼤问题拆分为相同性质的⼦问题,最后合并⼦问题的解来构成最终解。
⽽动态规划是,将⼦问题拆解后,按顺序求解⼦问题,前⾯阶段的求解为后⼀阶段提供有⽤信息,通过动态的选择来到达最终解。
⽤图来表⽰就是如下所⽰:⼆、适⽤情况(1)最优化原理:如果问题的最优解所包含的⼦问题的解也是最优的,就称该问题具有最优⼦结构,即满⾜最优化原理。
(2)⽆后效性:即某阶段状态⼀旦确定,就不受这个状态以后决策的影响。
也就是说,某状态以后的过程不会影响以前的状态,只与当前状态有关。
(3)有重叠⼦问题:即⼦问题之间是不独⽴的,⼀个⼦问题在下⼀阶段决策中可能被多次使⽤到。
(该性质并不是动态规划适⽤的必要条件,但是如果没有这条性质,动态规划算法同其他算法相⽐就不具备优势)----摘⾃百度百科三、求解步骤动态规划中有三个⾮常重要的概念:最优⼦结构、边界、状态转移公式。
最优⼦结构:最优⼦结构指的是,问题的最优解包含⼦问题的最优解。
反过来说就是,我们可以通过⼦问题的最优解,推导出问题的最优解。
边界:就是问题的出⼝。
状态转移公式:动态规划问题的这⼀阶段的最优解是可以通过前⾯阶段的解和上⼀阶段的决策推导出来的。
这个推导过程就是⼀个状态转移公式我们通常按照如下4个步骤设计⼀个动态规划算法:1.刻画⼀个最优解的结构特征2.递归地定义最优解的值3.计算最优解的值,通常采⽤⾃底向上的⽅法(采⽤⼀张表格记录之前的状态)4.利⽤计算出的信息构造⼀个最优解我们之前的和也是⼀样的求解步骤。
以硬币找零问题为例:⾸先,⾯对⼀枚新的硬币,我们有两个选择:使⽤和不使⽤。
构成当前阶段的最优解 = min{使⽤这枚硬币的解,不使⽤这枚硬币的解} ----(1.刻画⼀个最优解的结构特征)然后,我们就得到转移⽅程 Value(i) = min {Value(i-1), Value(s-c[i])) + 1} ---- (2.递归地定义最优解的值)之后我们从找零1⾓开始算起,⼀直到达我们想要找零的数⽬。
什么是动态规划动态规划( D ynamic P rogramming ,所以我们简称动态规划为 DP )是的⼀个分⽀,是求解决策过程(decision process) 最优化的数学⽅法。
20 世纪 50 年代初数学家R.E.Bellman 等⼈在研究多阶段决策过程 (multistep decision process) 的优化问题时,提出了著名的最优化原理 (principle of optimality),把多阶段过程转化为⼀系列单阶段问题,利⽤各阶段之间的关系,逐个求解,创⽴了解决这类过程优化问题的新⽅法 —— 动态规划。
1957 年出版了他的名著《 Dynamic Programming 》,这是该领域的第⼀本著作。
动态规划算法通常基于⼀个递推公式及⼀个或多个初始状态。
当前⼦问题的解将由上⼀次⼦问题的解推出。
使⽤动态规划来解题只需要多项式时间复杂度,因此它⽐回溯法、暴⼒法等要快许多。
说了这么多术语,想必⼤家都很头疼,现在让我们通过⼀个例⼦来了解⼀下DP 的基本原理。
⾸先,我们要找到某个状态的最优解,然后在它的帮助下,找到下⼀个状态的最优解。
这句话暂时理解不了没关系,请看下⾯的例⼦ :如果我们有⾯值为1 元、 3 元和 5 元的硬币若⼲枚,如何⽤最少的硬币凑够 11 元?我们凭直观感觉告诉⾃⼰,先选⾯值最⼤,因此最多选 2枚 5 元的硬币,现在是 10 元了,还差⼀元,接下来我们挑选第⼆⼤的 3 元硬币,发现不⾏( 10+3=13 超了),因此我们继续选第三⼤的硬币也就是 1元硬币,选⼀个就可以( 10+1=11 ),所以总共⽤了 3 枚硬币凑够了 11 元。
这就是贪⼼法,每次选最⼤的。
但是我们将⾯值改为 2 元, 3 元和 5 元的硬币,再⽤贪⼼法就不⾏了。
为什么呢?按照贪⼼思路,我们同样先取 2 枚最⼤ 5 元硬币,现在 10 元了,还差⼀元,接下来选第⼆⼤的,发现不⾏,再选第三⼤的,还是不⾏,这时⽤贪⼼⽅法永远凑不出 11 元,但是你仔细看看,其实我们可以凑出 11 元的, 2 枚 3元硬币和 1 枚五元硬币就⾏了,这是⼈经过思考判断出来了的,但是怎么让计算机算出来呢?这就要⽤动态规划的思想:⾸先我们思考⼀个问题,如何⽤最少的硬币凑够i 元 (i<11) ?为什么要这么问呢?两个原因: 1. 当我们遇到⼀个⼤问题时,总是习惯把问题的规模变⼩,这样便于分析讨论。
运筹学动态规划的概念运筹学中的动态规划是一种解决多阶段决策问题的数学方法。
它适用于需要做出一系列决策才能获得最优解的情况。
在这种情况下,每个决策都会对接下来的决策产生影响,因此需要考虑整个过程的影响。
动态规划的实质是将多阶段决策过程拆解成一系列子问题,每个子问题都可以用一个状态来描述。
通过求解每个子问题的最优解,就可以逐步得到整个过程的最优解。
动态规划的基本思想是以最优子结构为基础,避免重复计算已经求解过的子问题的过程。
也就是说,如果我们已经知道了子问题的最优解,那么整个问题的最优解就可以通过这些子问题的最优解推导出来。
通常情况下,动态规划问题需要满足以下几个条件:1.具有最优子结构特征:问题的最优解是由子问题的最优解组合而成的。
2.无后效性:子问题的解一旦确定,就不会被改变。
3.子问题重复性:不同的子问题可能会对应相同的状态。
4.边界性:即为问题的较小的子问题需要单独处理。
通过以上条件,我们就可以将动态规划问题分解为一个个子问题,并求解每个子问题所对应的最优值。
动态规划的基本流程分为三个步骤:1.定义状态:构建状态转移方程需要定义状态,状态通常用一个或多个变量来表示,变量的取值代表状态。
2.写出状态转移方程:根据定义好的状态,写出各个状态之间的转移方程。
3.确定边界条件:对较小的子问题需要单独处理,因此当状态变量为边界值时,需要特殊处理。
动态规划的应用广泛,它可以用于解决大量的问题。
例如,求解最长公共子序列问题、背包问题、最短路问题、字符串编辑距离问题等等。
它在图像处理、自然语言处理、生物信息学等领域中也有广泛的应用,如图像去噪、序列比对、DNA 序列匹配等。
总之,动态规划是运筹学中一种解决多阶段决策问题的重要方法,它通过将问题分解成子问题,并求解每个子问题的最优解,得出整个问题的最优解。
在实际应用中,我们需要根据具体问题特点,定义好状态,写出好的状态转移方程,才能有效地解决问题。
数据结构之动态规划动态规划的基本思想和常见应用场景动态规划(Dynamic Programming,DP)是一种通过将问题分解为更小的子问题来解决复杂问题的方法。
它的基本思想是利用已解决过的子问题的解来求解当前问题的解,从而避免重复计算,提高算法效率。
动态规划的应用广泛,可以用于解决一些优化问题、最优化问题以及组合优化问题等。
动态规划的基本思想可以用以下三个步骤来概括:1. 定义子问题:将原问题划分为一个或多个子问题,并找到它们之间的关系。
2. 构建状态转移方程:根据子问题之间的关系,找到问题的递推关系,将问题转化为子问题的解。
3. 解决问题:通过递推计算或者自底向上的方法,求解问题的最终解。
动态规划的核心是状态转移方程。
状态转移方程描述了子问题与原问题之间的关系,通过它可以求解原问题的解。
在构建状态转移方程时,需要考虑如何选择最优子结构并进行状态转移,以及确定初始状态和边界条件。
动态规划常见的应用场景包括:1. 最优化问题:如最短路径问题、最长递增子序列问题、背包问题等。
这类问题中,动态规划可以帮助我们找到最优解。
2. 组合优化问题:如旅行商问题(TSP)、任务分配问题等。
这类问题中,动态规划可以帮助我们找到最佳的组合方案。
3. 概率计算问题:如概率图模型中的推断问题、隐马尔可夫模型中的预测问题等。
这类问题中,动态规划可以帮助我们计算复杂的概率。
举例来说,我们可以通过动态规划求解最长递增子序列问题。
给定一个序列,我们希望找到其中最长递增的子序列的长度。
首先,定义状态dp[i]表示以第i个元素结尾的最长递增子序列的长度。
然后,我们可以根据dp[i-1]和第i个元素的大小关系来更新dp[i]的值,即dp[i]= max(dp[i], dp[j]+1),其中j为i之前的某个位置,且nums[j] < nums[i]。
最后,我们通过遍历数组,找到dp数组中的最大值,即可得到最长递增子序列的长度。
动态规划的特点及其应用摘要:本文的主要内容就是分析它的特点。
第一部分首先探究了动态规划的本质,因为动态规划的特点是由它的本质所决定的。
第二部分从动态规划的设计和实现这两个角度分析了动态规划的多样性、模式性、技巧性这三个特点。
第三部分将动态规划和递推、搜索、网络流这三个相关算法作了比较,从中探寻动态规划的一些更深层次的特点。
文章在分析动态规划的特点的同时,还根据这些特点分析了我们在解题中应该怎样利用这些特点,怎样运用动态规划。
这对我们的解题实践有一定的指导意义。
本文介绍了动态规划的基本思想和基本步骤,通过实例研究了利用动态规划设计算法的具体途径,讨论了动态规划的一些实现技巧,并将动态规划和其他一些算法作了比较,最后还简单介绍了动态规划的数学理论基础和当前最新的研究成果。
关键词: 动态规划,阶段1 引言动态规划是运筹学的一个分支,是求解决策过程最优化的数学方法。
20世纪50年代初美国数学家R.E.Bellman 等人在研究多阶段决策过程(multistep decision process)的优化问题时,提出了著名的最优化原理(principle of optimality),把多阶段过程转化为一系列单阶段问题,逐个求解,创立了解决这类过程优化问题的新方法——动态规划。
1957年出版了他的名著Dynamic Programming,这是该领域的第一本著作。
动态规划问世以来,在经济管理、生产调度、工程技术和最优控制等方面得到了广泛的应用。
例如最短路线、库存管理、资源分配、设备更新、排序、装载等问题,用动态规划方法比用其它方法求解更为方便。
虽然动态规划主要用于求解以时间划分阶段的动态过程的优化问题,但是一些与时间无关的静态规划(如线性规划、非线性规划),只要人为地引进时间因素,把它视为多阶段决策过程,也可以用动态规划方法方便地求解。
2 动态规划的基本思想一般来说,只要问题可以划分成规模更小的子问题,并且原问题的最优解中包含了子问题的最优解(即满足最优子化原理),则可以考虑用动态规划解决。
动态规划的实质是分治思想和解决冗余,因此,动态规划是一种将问题实例分解为更小的、相似的子问题,并存储子问题的解而避免计算重复的子问题,以解决最优化问题的算法策略。
由此可知,动态规划法与分治法和贪心法类似,它们都是将问题实例归纳为更小的、相似的子问题,并通过求解子问题产生一个全局最优解。
其中贪心法的当前选择可能要依赖已经作出的所有选择,但不依赖于有待于做出的选择和子问题。
因此贪心法自顶向下,一步一步地作出贪心选择;而分治法中的各个子问题是独立的(即不包含公共的子子问题),因此一旦递归地求出各子问题的解后,便可自下而上地将子问题的解合并成问题的解。
但不足的是,如果当前选择可能要依赖子问题的解时,则难以通过局部的贪心策略达到全局最优解;如果各子问题是不独立的,则分治法要做许多不必要的工作,重复地解公共的子问题。
解决上述问题的办法是利用动态规划。
该方法主要应用于最优化问题,这类问题会有多种可能的解,每个解都有一个值,而动态规划找出其中最优(最大或最小)值的解。
若存在若干个取最优值的解的话,它只取其中的一个。
在求解过程中,该方法也是通过求解局部子问题的解达到全局最优解,但与分治法和贪心法不同的是,动态规划允许这些子问题不独立,(亦即各子问题可包含公共的子子问题)也允许其通过自身子问题的解作出选择,该方法对每一个子问题只解一次,并将结果保存起来,避免每次碰到时都要重复计算。
因此,动态规划法所针对的问题有一个显著的特征,即它所对应的子问题树中的子问题呈现大量的重复。
动态规划法的关键就在于,对于重复出现的子问题,只在第一次遇到时加以求解,并把答案保存起来,让以后再遇到时直接引用,不必重新求解。
3 动态算法的基本步骤设计一个标准的动态规划算法,通常可按以下几个步骤进行:1.划分阶段:按照问题的时间或空间特征,把问题分为若干个阶段。
注意这若干个阶段一定要是有序的或者是可排序的(即无后向性),否则问题就无法用动态规划求解。
2.选择状态:将问题发展到各个阶段时所处于的各种客观情况用不同的状态表示出来。
当然,状态的选择要满足无后效性。
确定决策并写出状态转移方程,之所以把这两步放在一起,是因为决策和状态转移有着天然的联系,状态转移就是根据上一阶段的状态和决策来导出本阶段的状态。
所以,如果我们确定了决策,状态转移方程也就写出来了。
但事实上,我们常常是反过来做,根据相邻两段的各状态之间的关系来确定决策。
3.写出规划方程(包括边界条件):动态规划的基本方程是规划方程的通用形式化表达式。
一般说来,只要阶段、状态、决策和状态转移确定了,这一步还是比较简单的。
4 动态规划的适用条件任何思想方法都有一定的局限性,超出了特定条件,它就失去了作用。
同样,动态规划也并不是万能的。
适用动态规划的问题必须满足最优化原理和无后效性。
1.最优化原理(最优子结构性质)最优化原理可这样阐述:一个最优化策略具有这样的性质,不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。
简而言之,一个最优化策略的子策略总是最优的。
一个问题满足最优化原理又称其具有最优子结构性质。
最优化原理是动态规划的基础,任何问题,如果失去了最优化原理的支持,就不可能用动态规划方法计算。
动态规划的最优化理在其指标函数的可分离性和单调性中得到体现。
根据最优化原理导出的动态规划基本方程是解决一切动态规划问题的基本方法。
2.无后向性将各阶段按照一定的次序排列好之后,对于某个给定的阶段状态,它以前各阶段的状态无法直接影响它未来的决策,而只能通过当前的这个状态。
换句话说,每个状态都是过去历史的一个完整总结。
这就是无后向性,又称为无后效性。
有些问题乍一看好像有后向性,但如果按照某种合理的方式重新划分阶段,就可以发现其本质上是无后向性的,所以关键是阶段的合理划分,这一点将在动态规划的技巧中详细阐述。
3.子问题的重叠性动态规划可以将原来具有指数级复杂度的搜索算法改进成具有多项式时间的算法。
其中的关键在于解决冗余,这是动态规划算法的根本目的。
动态规划实质上是一种以空间换时间的技术,它在实现的过程中,不得不存储产生过程中的各种状态,所以它的空间复杂度要大于其它的算法。
以Bitonic旅行路线问题为例,这个问题也可以用搜索算法来解决。
动态规划的时间复杂度为O(n^2),搜索算法的时间复杂度为O(n!) ,但从空间复杂度来看,动态规划算法为O(n^2),而搜索算法为O(n),搜索算法反而优于动态规划算法。
选择动态规划算法是因为动态规划算法在空间上可以承受,而搜索算法在时间上却无法承受,所以我们舍空间而取时间。
设原问题的规模为n,容易看出,当子问题树中的子问题总数是n的超多项式函数,而不同的子问题数只是n的多项式函数时,动态规划法显得特别有意义,此时动态规划法具有线性时间复杂性。
所以,能够用动态规划解决的问题还有一个显著特征:子问题的重叠性。
这个性质并不是动态规划适用的必要条件,但是如果该性质无法满足,动态规划算法同其他算法相比就不具备优势。
六。
动态规划的技巧——阶段的划分和状态的表示在动态规划的设计过程中,阶段的划分和状态的表示是非常重要的两步,这两步会直接影响该问题的计算复杂性,有时候阶段划分或状态表示的不合理还会使得动态规划法不适用。
(下面的几个例子图较多,这里从略)有很多的多阶段决策问题都有着不止一种的阶段划分方法,因而往往就有不止一种的规划方法。
有时各种方法所产生的效果是差不多的,但更多的时候,就像我们的例子一样,两种方法会在某个方面有些区别。
所以,在用动态规划解题的时候,可以多想一想是否有其它的解法。
对于不同的解法,要注意比较,好的算法好在哪里,差一点的算法差在哪里。
从各种不同算法的比较中,我们可以更深刻地领会动态规划的构思技巧。
七。
动态规划实现中的问题应用动态规划解决问题,在有了基本的思路之后,一般来说,算法实现是比较好考虑的。
但有时也会遇到一些问题,而使算法难以实现。
动态规划思想设计的算法从整体上来看基本都是按照得出的递推关系式进行递推,这种递推相对于计算机来说,只要设计得当,效率往往是比较高的,这样在时间上溢出的可能性不大,而相反地,动态规划需要很大的空间以存储中间产生的结果,这样可以使包含同一个子问题的所有问题共用一个子问题解,从而体现动态规划的优越性,但这是以牺牲空间为代价的,为了有效地访问已有结果,数据也不易压缩存储,因而空间矛盾是比较突出的。
另一方面,动态规划的高时效性往往要通过大的测试数据体现出来(以与搜索作比较),因而,对于大规模的问题如何在基本不影响运行速度的条件下,解决空间溢出的问题,是动态规划解决问题时一个普遍会遇到的问题。
对于这个问题,可以考虑从以下一些方面去尝试:一个思考方向是尽可能少占用空间。
如从结点的数据结构上考虑,仅仅存储必不可少的内容,以及数据存储范围上精打细算(按位存储、压缩存储等)。
当然这要因问题而异,进行分析。
另外,在实现动态规划时,一个我们经常采用的方法是用一个与结点数一样多的数组来存储每一步的决策,这对于倒推求得一种实现最优解的方法是十分方便的,而且处理速度也有一些提高。
但是在内存空间紧张的情况下,我们就应该抓住问题的主要矛盾。
省去这个存储决策的数组,而改成在从最优解逐级倒推时,再计算一次,选择某个可能达到这个值的上一阶段的状态,直到推出结果为止。
这样做,在程序编写上比上一种做法稍微多花一点时间,运行的时效也可能会有一些(但往往很小)的下降,但却换来了很多的空间。
因而这种思想在处理某些问题时,是很有意义的。
但有时,即使采用这样的方法也会发现空间溢出的问题。
这时就要分析,这些保留下来的数据是否有必要同时存在于内存之中。
因为有很多问题,动态规划递推在处理后面的内容时,前面比较远处的内容实际上是用不着的。
对于这类问题,在已经确信不会再被使用的数据上覆盖数据,从而使空间得以重复利用,如果能有效地使用这一手段,对于相当大规模的问题,空间也不至于溢出(为了求出最优方案,保留每一步的决策仍是必要的,这同样需要空间)。
一般地说,这种方法可以通过两种思路来实现:一种是递推结果仅使用Data1和Data2这样两个数组,每次将Data1作为上一阶段,推得Data2数组,然后,将Data2通过复制覆盖到Data1之上,如此反复,即可推得最终结果。
这种做法有一个局限性,就是对于递推与前面若干阶段相关的问题,这种做法就比较麻烦;而且,每递推一级,就需要复制很多的内容,与前面多个阶段相关的问题影响更大。
另外一种实现方法是,对于一个可能与前N个阶段相关的问题,建立数组Data[0..N],其中各项为最近N各阶段的保存数据。