动态规划具体概念+例题
示例
贪心法
N=5 石子数分别为3 4 6 5 4 2。 用贪心法的合并过程如下: 第一次 3 4 6 5 4 2得分 5 第二次 5 4 6 5 4得分9 第三次 9 6 5 4得分9 第四次 9 6 9得分15 第五次 15 9得分24 第六次24 总分:62 然而仔细琢磨后,发现更好的方案: 第一次3 4 6 5 4 2得分 7 第二次7 6 5 4 2得分13 第三次13 5 4 2得分6 第四次13 5 6得分11 第五次 13 11得分24 第六次24 总分:61
三、适用的情况
能采用动态规划求解的问题一般要具有3个性质: (1) 最优子结构:如果问题的最优解所包 含的子问题的解也是最优的,就称该问题具 有最优子结构,即满足最优化原理。
(2) 无后效性:即某阶段状态一旦确定, 就不受这个状态以后决策的影响。也就是说, 某状态以后的过程不会影响以前的状态,只 与当前状态有关。
记忆化搜索
Opt[i, j] - 每产生一个f(i, j), 将f(i, j)的值放入opt中,以后再 次调用到f(i, j)的时候,直接从 记忆化的功效 opt[i, j]来取就可以了。 于是动态规划的状态转移方程被直 观地表示出来了,这样节省了思维 的难度,减少了编程的技巧,而运 行时间只是相差常数的复杂度,而 且在相当多的情况下,递归算法能 更好地避免浪费,在比赛中是非常 实用的.
动态规划
什么是动态规划
在学习动态规划之前你一定学 过搜索.那么搜索与动态规划有 什么关系呢?我们来下面的一 个例子.
数字三角形
给你一个数字三角形, 形式如下 : 1 2 3 4 5 6 7 8 9 10 找出从第一层到最后一层的一条 路,使得所经过的权值之和最小或 者最大.
数字三角形
无论对与新手还是老手,这都是再 熟悉不过的题了,很容易地,我们 写出状态转移方程:f(i, j)=a[i, j] + min{f(i-1, j)+f(i-1, j + 1)} 对于动态规划算法解决这个问题, 我们根据状态转移方程和状态转移 方向,比较容易地写出动态规划的 循环表示方法。但是,当状态和转 移非常复杂的时候,也许写出循环 式的动态规划就不是那么简单了。 解决方法:
显然,贪心法是错误的。
动态规划
用data[i,j]表示将从第i颗石子开始的接下来j颗石子合并所 得的分值, max[i,j]表示将从第i颗石子开始的接下来j颗石子合并可能 的最大值,那么: max[i,j] = max(max[i, k] + max[i + k, j – k] + data[i,k] + data[i+k, j–k]) (2<=k<=j) max[i,1] = 0 同样的,我们用min[i,j]表示将第从第i颗石子开始的接下来 j颗石子合并所得的最小值,可以得到类似的方程: min[i,j] = min(min[i, k] + min[i + k, j – k] + data[i,k] + data[i+k, j– k]) (0<=k<=j) min[i,0] = 0 这样,我们完美地解决了这道题。时间复杂度也是O(n2) 。
记忆化搜索
我们尝试从正面的思路去分析问题 ,如上例,不难得出一个非常简单 的递归过程 : f1:=f(i-1,j+1); f2:=f(i-1,j); if f1>f2 then f:=f1+a[i,j] else f:=f2+a[i,j]; 显而易见,这个算法就是最简单的 搜索算法。时间复杂度为2n,明显 是会超时的。分析一下搜索的过程 ,实际上,很多调用都是不必要的 ,也就是把产生过的最优状态,又 产生了一次。为了避免浪费,很显 然,我们存放一个opt数组:
初始状态→│决策1│→│决策2│→…→│决 策n│→结束状态 (1)划分阶段:按照问题的时间或空间特 征,把问题分为若干个阶段。在划分阶段时, 注意划分后的阶段一定要是有序的或者是可 排序的,否则问题就无法求解。
(2)确定状态和状态变量:将问题发展到 各个阶段时所处于的各种客观情况用不同的 状态表示出来。当然,状态的选择要满足无 后效性。 (3)确定决策并写出状态转移方程:因为 决策和状态转移有着天然的联系,状态转移 就是根据上一阶段的状态和决策来导出本阶 段的状态。所以如果确定了决策,状态转移 方程也就可写出。但事实上常常是反过来做, 根据相邻两个阶段的状态之间的关系来确定 决策方法和状态转移方程。
动态规划的实质
可以看出动态规划的实质就是
这也就是为什么我们常说动态规划必须满 足重叠子问题的原因.记忆化,正符合了这个 要求.
状态 阶段 决策
或许有一种对动态规划的简单 称法,叫分阶段决策.其实我认为 这个称法并不是很能让人理解. 那么下面我们来看看阶段,状态, 决策这三者间得关系吧.
dp[i][j]=max(dp[i-1][j-1],dp[i-1][j])+a[i][j];
如果看到这里,相信你一定给这篇演 示文稿看完了,预祝你在NOIP2006里取 得好的成绩! ——ljf or BraveHeart (其实是ljfhe和BraveHeart做的PPT )
由于动态规划解决的问题多数有重叠子问 题这个特点,为减少重复计算,对每一个 子问题只解一次,将其不同阶段的不同状 态保存在一个二维数组中。
与分治法最大的差别是:适合于用动态规 划法求解的问题,经分解后得到的子问题 往往不是互相独立的(即下一个子阶段的 求解是建立在上一个子阶段的解的基础上, 进行进一步的求解)。
要点小结
动态规划方程要点:变量定义,方程递归 形式,参数范围,初始条件。 程序模型要点: 初始条件->变量初始化|递归终止条件 参数范围->循环变量范围&判断条件 方程递归形式->赋值语句
01背包
若01背包问题中,背包容量上限为 T(<=100)。求解。
动态规划方程
变量的定义: Vi ::= 第i件物品的体积 Pi ::= 第i件物品的价值 fi j ::= 用容量为j的背包去装前i个物品所能 获得的最大总价值 方程: fi j = max{fi-1 j, fi-1 j-vi+Pi} 1<=i<=j f0 j = 0 Answer = fn T
(4)寻找边界条件:给出的状态转移方程 是一个递推式,需要一个递推的终止条件或 边界条件。
一般,只要解决问题的阶段、状态和状 态转移决策确定了,就可以写出状态转移方 程(包括边界条件)。
五、算法实现的说明
(1)问题的阶段 (2)每个阶段的状态 (3)从前一个阶段转化到后一个阶段之间 的递推关系。 递推关系必须是从次小的问题开始到较大 的问题之间的转化,从这个角度来说,动 态规划往往可以用递归程序来实现,不过 因为递推可以充分利用前面保存的子问题 的解来减少重复计算,所以对于大规模问 题来说,有递归不可比拟的优势,这也是 动态规划算法的核心之处。
平面型动态规划
特征:问题模型为一个平面 通常的子结构划分方式:逐行扫描
宝藏三角
一个宝藏如下所示: 3 4 5 9 7 2 6 8 7 4 从顶端出发,每次可以向左下或者右下走。 求一条从顶端到底边的路径,使得路径上 所有宝藏之和最大。
动态规划方程
状态转移方程:
无后效性
最短路径:当前选择任何一条边都不会影 响以后选择其他边。 有费用的最短路径:设经过任何一条边时 都要耗费一定的费用,总费用一定的情况 下,当前选择某一条特定的边可能导致某 些其他的边无法被选择。
四、求解的基本步骤
动态规划所处理的问题是一个多阶段决策 问题,一般由初始状态开始,通过对中间 阶段决策的选择,达到结束状态。这些决 策形成了一个决策序列,同时确定了完成 整个过程的一条活动路线(通常是求最优的 活动路线)。如图所示。动态规划的设计都 有着一定的模式,一般要经历以下几个步 骤。
决策
显然,从上图可以看出,当前状态通 过决策,回到了以前状态.可见决策 其实就是状态之间的桥梁。而以前 状态也就决定了当前状态的情况。
数字三角形的决策就是选择相邻的两 个以前状态的最优值。
动规的要诀-状态
我们一般在动规的时候所用到的一 些数组,也就是用来存储每个状态 的最优值的。 我们就从动态规划的要诀,也就是 核心部分“状态”开始,来逐步了 解动态规划。
线型动态规划
特征:问题的数学模型表现为线型。 通常的子结构划分方式:顺序、中分
最长不下降序列
设 有 整 数 序 列 b1,b2,b3,…,bm , 若 存 在 下 标 i1<i2<i3< …<in,且bi1<bi2<bi3< …<bin,则称 b1,b2,b3,…,bm中有长度为n的不下降序列bi1 , bi2 ,bi3 ,…,bin 。 求序列 b1,b2,b3,…,bm 中所有长度 (n) 最大不下降 子序列 输入:整数序列。 输出:最大长度n和所有长度为n的序列个数。
状态 阶段 决策
状态是表现出动态规划核心思想的一个东西.而分 阶段决策这个东西有似乎没有提到状态,这是不科 学的. 阶段,有些题目并不一定表现出一定的阶段性.数字 三角形的阶段就是每一层.这里我们引入一个概念 ---以前状态.但阶段不是以前状态,状态是阶段的表 现形式.数字三角形的以前状态就是当前层的前一 层. 那什么是决策呢?我们看看下面一张图就知道了.
一、基本概念
动态规划过程是:每次决策依赖于当前状 态,又随即引起状态的转移。一个决策序 列就是在变化的状态中产生出来的,所以, 这种多阶段最优化决策解决问题的过程就 称为动态规划。
二、基本思想与策略
基本思想与分治法类似,也是将待求解的 问题分解为若干个子问题(阶段),按顺 序求解子阶段,前一子问题的解,为后一 子问题的求解提供了有用的信息。在求解 任一子问题时,列出各种可能的局部解, 通过决策保留那些有可能达到最优的局部 解,丢弃其他局部解。依次解决各子问题, 最后一个子问题就是初始问题的解。