动态规划算法举例分析
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
动态规划算法
1. 动态规划算法介绍
基本思想是将待求解问题分解成若干子问题,先求解子问题,最后用这些子问题带到原问题,与分治算法的不同是,经分解得到的子问题往往是不是相互独立,若用分治则子问题太多。
2. 适用动态规划算法问题的特征
(1)最优子结构
设计动态规划算法的第一步骤通常是要刻画最优解的结构。当问题的最优解包含了其子问题的最优解时,称该问题具有最优子结构性质。问题的最优子结构性质提供了该问题可用动态规划算法求解的重要线索。
在动态规划算法中,问题的最优子结构性质使我们能够以自底向下的方式递归地从子问题的最优解逐步构造出整个问题的最优解。同时,它也使我们能在相对小的子问题空间中考虑问题。
(2)重叠子问题
可用动态规划算法求解的问题应具备的另一基本要素是子问题的重叠性质。在用递归算法自顶向下解此问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次。动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只解一次,而后将其解保存在一个表格中,当再次需要解此子问题时,只有简单地用常数时间查看一下结果。通常,不同的子问题个数随输入问题的大小呈多项式增长。因此,用动态规划算法通常只需要多项式时间,从而获得较高的解题效率。
(3)备忘录方法
动态规划算法的一个变形是备忘录方法。备忘录方法也是一个表格来保存已解决的子问题的答案,在下次需要解此子问题时,只要简单地查看该子问题的解答,而不必重新计算。与动态规划算法不同的是,备忘录方法的递归方式是自顶向下的,而动态规划算法则是自底向上递归的。因此,备忘录方法的控制结构与直接递归方法的控制结构相同,区别在于备忘录方法为每个解过的子问题建立了备忘录以备需要时查看,避免了相同子问题的重复求解。
备忘录方法为每个子问题建立一个记录项,初始化时,该记录项存入一个特殊的值,表示该子问题尚未求解。在求解过程中,对每个待求的子问题,首先查看其相应的记录项。若记录项中存储的是初始化时存入的特殊值,则表示该子问题是第一次遇到,则此时计算出该子问题的解,并保存在其相应的记录项中。若记录项中存储的已不是初始化时存入的特殊值,则表示该子问题已被计算过,其相应的记录项中存储的是该子问题的解答。此时,只要从记录项中取出该子问题的解答即可。
3. 基本步骤
a 、找出最优解的性质,并刻画其结构特征。
b 、递归地定义最优值。
c 、以自底向上的方式计算出最优值。
d 、根据计算最优值时得到的信息构造一个最优解。(可省) 例1-1 [0/1背包问题] [问题描述]
用贪心算法不能保证求出最优解。在0/1背包问题中,需要对容量为c 的背包进行装载。从n 个物品中选取装入背包的物品,每件物品i 的重量为i
w ,价
值为
i
v 。对于可行的背包装载,背包中物品的总重量不能超过背包的容量,最佳
装载是指所装入的物品价值最高,即∑=n
i i
i
x v
1
取得最大值。约束条件为
c
x w
n
i i i
≤∑=1
,
{}()
n i x i ≤≤∈11,0。
在这个表达式中,需要求i x的值。i x=1表示物品i装入背包中,i x=0表示物品i不装入背包。
1.找出最优解性质
考察上述0 / 1背包问题。如前所述,在该问题中需要决定x1,…,xn的值。假设按i = 1,2,…,n 的次序来确定xi 的值。如果置x1 = 0,则问题转变为相对于其余物品(即物品2,3,…,n),背包容量仍为c 的背包问题。若置x1 = 1,问题就变为关于最大背包容量为c-w1 的问题。现设r∈{c,c-w1 } 为剩余的背包容量。
在第一次决策之后,剩下的问题便是考虑背包容量为r 时的决策。不管x1 是0或是1,[x2 ,…,xn ] 必须是第一次决策之后的一个最优方案,如果不是,则会有一个更好的方案[y2,…,yn ],因而[x1,y2,…,yn ]是一个更好
的方案。因此最优解符合条件,
c
x
w
y
w
x
w
n
i
i
i
n
i
i
i
≤
+
≤∑
∑
=
=2
1
1
1。
例:假设n=3, w=[100,14,10], p=[20,18,15], c= 116。若设x1 = 1,则在本次决策之后,可用的背包容量为r= 116-100=16 。[x2,x3 ]=[0,1] 符合容量限制的条件,所得值为1 5,但因为[x2,x3 ]= [1,0] 同样符合容量条件且所得值为1 8,因此[x2,x3 ] = [ 0,1] 并非最优策略。即x= [ 1,0,1] 可改进为x= [ 1,1,0 ]。若设x1 = 0,则对于剩下的两种物品而言,容量限制条件为11 6。总之,如果子问题的结果[x2,x3 ]不是剩余情况下的一个最优解,则[x1,x2,x3 ]也不会是总体的最优解。
2.递归定义最优解
在上述例题的0 / 1背包问题中,最优决策序列由最优决策子序列组成。假设m(i,v) 表示例子中剩余容量为j,剩余物品为i,i+1,…,n 时的最优解的值,即:
n
n n
w j w j v j n m ≤≤≥⎩⎨
⎧=00
),( (1)
和
{}i
i i i w j w j j i m v w j i m j i m j i m ≤≥⎩
⎨
⎧++-++=0)
,1(),1(),,1(max ),((2)
因此,m (1,c )是初始时最优问题的最优解。
现在计算xi 值,步骤如下:若m(1 ,c) =m( 2 ,c),则x1 = 0,否则x1 = 1。接下来需从剩余容量c-w1中寻求最优解,用m(2, c-w1) 表示最优解。依此类推,可得到所有的xi (i= 1,2,…,n) 值。 [0/1背包问题的C 语言实现算法]
#define N 12
void Knapsack(int v[],int w[],int c,int n,int m[6][N]) {
int i,j,jMax,k;
jMax=(w[n]-1 for(i=w[n];i<=c;i++) m[n][i]=v[n]; for(i=n-1;i>1;i--) { jMax=(w[i]-1 { k=j-w[i]; if(m[i+1][j] m[i][j]=m[i+1][j]; } } m[1][c]=m[2][c]; if(c>=w[1]) {