一、基本概念
动态规划过程是:每次决策依赖于当前状态,又随即引起状态的转移。一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划。
二、基本思想与策略
基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。
由于动态规划解决的问题多数有重叠子问题这个特点,为减少重复计算,对每一个子问题只解一次,将其不同阶段的不同状态保存在一个二维数组中。
与分治法最大的差别是:适合于用动态规划法求解的问题,经分解后得到的子问题往往不是互相独立的(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解)。
三、适用的情况
能采用动态规划求解的问题的一般要具有3个性质:
(1) 最优化原理:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构,即满足最优化原理。
(2) 无后效性:即某阶段状态一旦确定,就不受这个状态以后决策的影响。也就是说,某状态以后的过程不会影响以前的状态,只与当前状态有关。
(3)有重叠子问题:即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到。(该性质并不是动态规划适用的必要条件,但是如果没有这条性质,动态规划算法同其他算法相比就不具备优势)
四、求解的基本步骤
动态规划所处理的问题是一个多阶段决策问题,一般由初始状态开始,通过对中间阶段决策的选择,达到结束状态。这些决策形成了一个决策序列,同时确定了完成整个过程的一条活动路线(通常是求最优的活动路线)。如图所示。动态规划的设计都有着一定的模式,一般要经历以下几个步骤。
初始状态→│决策1│→│决策2│→…→│决策n│→结束状态
图1 动态规划决策过程示意图
(1)划分阶段:按照问题的时间或空间特征,把问题分为若干个阶段。在划分阶段时,注意划分后的阶段一定要是有序的或者是可排序的,否则问题就无法求解。
(2)确定状态和状态变量:将问题发展到各个阶段时所处于的各种客观情况用不同的状态表示出来。当然,状态的选择要满足无后效性。
(3)确定决策并写出状态转移方程:因为决策和状态转移有着天然的联系,状态转移就是根据上一阶段的状态和决策来导出本阶段的状态。所以如果确定了决策,状态转移方程也就可写出。但事实上常常是反过来做,根据相邻两个阶段的状态之间的关系来确定决策方法和状态转移方程。
(4)寻找边界条件:给出的状态转移方程是一个递推式,需要一个递推的终止条件或边界条件。
一般,只要解决问题的阶段、状态和状态转移决策确定了,就可以写出状态转移方程(包括边界条件)。
实际应用中可以按以下几个简化的步骤进行设计:
(1)分析最优解的性质,并刻画其结构特征。
(2)递归的定义最优解。
(3)以自底向上或自顶向下的记忆化方式(备忘录法)计算出最优值
(4)根据计算最优值时得到的信息,构造问题的最优解
五、算法实现的说明
动态规划的主要难点在于理论上的设计,也就是上面4个步骤的确定,一旦设计完成,实现部分就会非常简单。
使用动态规划求解问题,最重要的就是确定动态规划三要素:
(1)问题的阶段 (2)每个阶段的状态
(3)从前一个阶段转化到后一个阶段之间的递推关系。
递推关系必须是从次小的问题开始到较大的问题之间的转化,从这个角度来说,动态规划往往可以用递归程序来实现,不过因为递推可以充分利用前面保存的子问题的解来减少重复计算,所以对于大规模问题来说,有递归不可比拟的优势,这也是动态规划算法的核心之处。
确定了动态规划的这三要素,整个求解过程就可以用一个最优决策表来描述,最优决策表是一个二维表,其中行表示决策的阶段,列表示问题状态,表格需要填写的数据一般对应此问题的在某个阶段某个状态下的最优值(如最短路径,最长公共子序列,最大价值等),填表的过程就是根据递推关系,从1行1列开始,以行或者列优先的顺序,依次填写表格,最后根据整个表格的数据通过简单的取舍或者运算求得问题的最优解。
五、算法应用示例
用一个实际例子来体现动态规划的算法思想——硬币找零问题。
硬币找零问题描述:现存在一堆面值为 V1、V2、V3 … 个单位的硬币,问最少需要多少个硬币才能找出总值为 T 个单位的零钱?假设这一堆面值分别为 1、2、5、21、25 元,需要找出总值 T 为 63 元的零钱。
很明显,只要拿出 3 个 21 元的硬币就凑够了 63 元了。
基于上述动态规划的思想,我们可以从 1 元开始计算出最少需要几个硬币,然后再求 2 元、3元…每一次求得的结果都保存在一个数组中,以后需要用到时则直接取出即可。那么我们什么时候需要这些子问题的解呢?如何体现出由子问题的解得到较大问题的解呢?
其实,在我们从 1 元开始依次找零时,可以尝试一下当前要找零的面值(这里指 1元)是否能够被分解成另一个已求解的面值的找零需要的硬币个数再加上这一堆硬币中的某个面值之和,如果这样分解之后最终的硬币数是最少的,那么问题就得到答案了。
单是上面的文字描述太抽象,先假定以下变量:
values[] : 保存每一种硬币的币值的数组
valueKinds :币值不同的硬币种类数量,即values[]数组的大小
money : 需要找零的面值
coinsUsed[] : 保存面值为 i 的纸币找零所需的最小硬币数
算法描述:
当求解总面值为 i 的找零最少硬币数 coinsUsed[ i ] 时,将其分解成求解 coinsUsed[ i– cents]和一个面值为cents元的硬币,由于 i– cents < i , 其解 coinsUsed[ i– cents] 已经存在,如果面值为 cents 的硬币满足题意,那么最终解 coinsUsed[ i ] 则等于 coinsUsed[ i– cents] 再加上 1(即面值为 cents)的这一个硬币。
下面用代码实现并测试一下:
0/1背包问题的动态规划法求解,前人之述备矣,这里所做的工作,不过是自己根据理解实现了一遍,主要目的还是锻炼思维和编程能力,同时,也是为了增进对动态规划法机制的理解和掌握。
值得提及的一个问题是,在用 JAVA 实现时, 是按算法模型建模,还是用对象模型建模呢? 如果用算法模型,那么 背包的值、重量就直接存入二个数组里;如果用对象模型,则要对背包以及背包问题进行对象建模。思来想去,还是采用了对象模型,尽管心里感觉算法模型似乎更好一些。有时确实就是这样,对象模型虽然现在很主流,但也不是万能的,采用其它的模型和视角,或许可以得到更好的解法。
背包建模:
分享到:
相关推荐
贪心算法、分治算法和动态规划是三种常用的算法设计策略,每种算法都有其特点和应用场景。下面我们将对这三种算法进行详细的比较和分析。 分治算法 分治算法是一种将原问题划分成若干个规模较小的子问题,然后递归...
五大常用算法-动态规划,分治,递归,贪心,回溯
"学习电脑信息五大常用算法之二:动态规划算法" 动态规划算法是五大常用算法之一,是解决多阶段决策问题的有效方法。它的基本思想是将问题分解为多个阶段,每个阶段都有其状态和决策,然后通过决策序列来解决问题。...
"五大常用算法之二:动态规划算法" 动态规划算法是五大常用算法之一,属于多阶段决策问题的解决方法。该算法的核心思想是将问题分解为多个阶段,每个阶段都有其对应的状态和决策,以便通过决策序列来达成最优解。 ...
贪心算法和动态规划是两种常用的算法设计方法,它们都可以用于解决复杂的问题,但是它们之间存在着一些关键的区别和联系。 首先,让我们了解一下贪心算法和动态规划的定义。 贪心算法是一种算法设计方法,它通过在...
动态规划算法是一种强大的算法设计技术,主要用于解决多阶段决策过程中的最优化问题。它的核心思想是通过将复杂问题分解为相互关联的子问题,并利用子问题的最优解来构建原问题的最优解。动态规划强调的是“空间换...
动态规划是一种强大的算法,尤其适用于解决最优化问题,如寻找最优解或最大值或最小值。以下是关于动态规划算法的详细解释: 1. **动态规划的概念**: 动态规划是一种通过将复杂问题分解为子问题来求解的方法。它...
贪心算法和动态规划是两种常用的算法设计方法,它们都可以用来解决优化问题,但它们的解决思路和应用场景不同。 贪心算法是一种解决优化问题的算法,通过在每一步都做出当前看起来最优的选择,来获取全局最优解。...
贪心算法和动态规划算法都是常用的算法设计策略,它们可以解决很多实际问题。但是,贪心算法不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性。动态规划算法则可以解决很多问题,但是需要注意避免...
动态规划和贪心算法是两种常用的算法思想,它们之间存在一定的关联和区别。在本文中,我们将详细介绍动态规划和贪心算法的定义、特点、区别和应用场景。 动态规划是一种算法思想,它通过将问题分解成多个小问题,...
动态规划算法的基本框架代码示例中,有两个嵌套循环,第一个循环遍历阶段(例如,工作任务),第二个循环更新每个阶段的状态。`f(i)`表示与阶段`i`相关的表达式,`xi[j]`表示在阶段`i`时选择任务`j`的状态。`g()`...
本篇文章将深入探讨"常用算法"这一主题,旨在帮助你理解并掌握这些算法的基本概念、应用场景及实现方法。 首先,让我们从排序算法开始。排序算法是计算机科学中最基础且广泛使用的算法之一,例如冒泡排序、插入排序...
本书可帮助读者快速理解并应用常见算法,如排序、搜索、动态规划等。书中分章节详细讲解了每种算法的原理、实现方式及其应用场景,使得读者能够将理论与实践相结合。源码部分则是直接用C语言编写,这要求读者需要...
学习电脑信息五大常用算法之二:动态规划算法,算法数据结构 五大常用算法
常用算法介绍,及其几道算法题,常见算法包括排序算法、搜索算法、动态规划、贪心算法、回溯算法、分治算法等
常用算法大全-动态规划算法.pdf
常用排序算法的动态演示系统 在本系统中,我们主要实现了五种常用的排序算法:冒泡排序法、快速排序法、直接插入排序法、折半插入排序法和树形选择排序法。这些算法都是在计算机科学中最基本和最重要的排序算法,...
数学建模30个常用算法(Python)数学建模30个常用算法(Python)数学建模30个常用算法(Python)数学建模30个常用算法(Python)数学建模30个常用算法(Python)数学建模30个常用算法(Python)数学建模30个常用算法...
综上所述,ACM常用算法涉及到的知识点广泛且深入,对于提升编程能力、解决实际问题具有重要作用。这些模板代码可以帮助学习者快速理解和应用这些算法,提高解决问题的效率。在实践中不断练习和优化这些算法,是提升...
二、动态规划算法思想实现 动态规划算法是一种基于最优子结构的算法思想,它将问题分解为多个小问题,然后将小问题的解决方案组合起来,得到原问题的解。动态规划算法可以解决许多复杂的问题,例如Fibonacci数列、...