第六章动态规划解析
第六章动态规划
6.1 动态规划的思想方法
6.1.1 动态规划的最优决策原理
活动过程划分为若干个阶段,每一阶段的决策,依赖于前一阶段的状态,由决策所采取的动作,使状态发生转移,成为下一阶段的决策依据。
P1P2 P n
S0S1 S2┅┅S n-1 S n
图6.1 动态规划的决策过程
最优性原理:无论过程的初始状态和初始决策是什么,其余决策都必须相对于初始决策所产生的状态,构成一个最优决策序列。
S0
p(1,1) p(1,2) p(1,r1)
s(1,1)
s(1,2) s(1,r1)
s(2,11) p(2,12) s(2,1r2) p(2,21) s(2,22) s(2,2r2) s(2,r11) s(2,r12) s(2,r1r2) 令最优状态为)
(s,由此倒推:
22
,2
s
p
p
→
,2(s
→
→
s→
)
)2,1(
22
)2,1(
)
,2(
22
最优决策序列,)
p→
)2,1(p
22
,2
(
状态转移序列:)
s
22
→
0s
s→
,2
(
)2,1(
赖以决策的策略或目标,称为动态规划函数。
整个决策过程,可以递归地进行,或用循环迭代的方法进行。
动态规划函数可以递归地定义,也可以用递推公式来表达。
最优决策是在最后阶段形成的,然后向前倒推,直到初始阶段;
而决策的具体结果及所产生的状态转移,却是由初始阶段开始进行计算的,然后向后递
6
6
归或迭代,直到最终结果。
6.1.2 动态规划实例、货郎担问题
例6.1 货郎担问题。
在有向赋权图>= 令),(V i d :从顶点i 出发,经V 中各顶点一次,最终回到顶点i 的最短路径的长度, 开始时,}{i V V -=。 动态规划函数: })}{,({min ),()}{,(k V k d c V i d i V i d ik V k -+==-∈(6.1.1) i k c k d ki ≠=),(? (6.1.2) 4个城市的费用矩阵是: ?? ? ? ? ? ? ? ?∞∞∞∞==573 24632576 3 )(ij c C 根据(6.1.1)式,由城市1出发,经城市2,3,4然后返回1的最短路径长度为: })}3,2{,4(,)}4,2{,3(,)}4,3{,2({min )}4,3,2{,1(141312d c d c d c d +++= 它必须依据)}3,2{,4(,)}4,2{,3(,)}4,3{,2(d d d 的计算结果: })}3{,4(,)}4{,3({min )}4,3{,2(2423d c d c d ++= })}2{,4(,)}4{,2({min )}4,2{,3(3432d c d c d ++= })}2{,3(,)}3{,2({min )}3,2{,4(4342d c d c d ++= 这一阶段的决策,又必须依据下面的计算结果: )}4{,2(,)}3{,4(,)}4{,3(d d d )}2{,3(,)}3{,2(,)}2{,4(,d d d 再向前倒推,有: 532),4()}4{,3(413434=+=+=+=c c d c d ? 1165),3()}3{,4(314343=+=+=+=c c d c d ? 633),4()}4{,2(412424=+=+=+=c c d c d ? 1257),2()}2{,4(214242=+=+=+=c c d c d ? 862),3()}3{,2(312323=+=+=+=c c d c d ? 954),2()}2{,3(213232=+=+=+=c c d c d ? 有了这些结果,再向后计算,有: 7}113,52{min )}4,3{,2(=++=d 路径顺序是:2,3,4,1 6 10}122,64{min )}4,2{,3(=++=d 路径顺序是:3,2,4,1 14}95,87{min )}3,2{,4(=++=d 路径顺序是:4,3,2,1 最后: 10}147,106,73{min )}4,3,2{,1(=+++=d 路径顺序是:1,2,3,4,1 d (1,{2,3,4}) d (2,{3,4}) d (3,{2,4}) d (4,{2,3}) d (3,{4}) d (4,{3}) d (2,{4}) d (4,{2}) d (2,{3}) d (3,{2}) d (4,φ) d (3,φ) d (4,φ) d (2,φ) d (3,φ) d (2,φ) 图6.2 货郎担问题求解过程示意图 二、复杂性分析 令i N 是计算从顶点i 出发,返回顶点i 所需计算的形式为)}{,(k V k d -的个数。 开始计算)}{,(i V i d -时,集合}{i V -中有1-n 个城市。 以后,在计算)}{,(k V k d -时,集合}{k V -的城市数目,在不同的决策阶段,分别为2-n ,┅,0。 在整个计算中,需要计算大小为j 的不同城市集合的个数为j n C 1-,1,1,0-=n j 。因此,总个数为: ∑-=-= 1 1 n j j n i C N 当}{k V -集合中的城市个数为j 时,为计算)}{,(k V k d -,需j 次加法, 1-j 次比较。从i 城市出发,经其它城市再回到i ,总的运算时间i T 为: ∑∑ ∑ -=--=--=-=?< ?= 1 1 1 01 1 1 n j j n n j j n n j j n i C n C n C j T 由二项式定理: j n j n j j n n y x C y x -=∑= +0 )( 令1==y x ;可得: )2(21n n i n O n T =?<- 则用动态规划方法求解货郎担问题,总的花费T 为: )2(22121 n n n i i n O n T T =?<= -=∑ 6 6.2 多段图的最短路径问题 6.2.1 多段图的决策过程 定义 6.1 有向连通赋权图),,(W E V G =,顶点集合V 划分成k 个不相交的子集i V ,k i ≤≤1,2≥k ,使得E 中的任一边),(v u ,必有i V u ∈,m i V v +∈,1≥m 。称为多段图。 令1||||1==k V V ,称1V s ∈为源点,k V t ∈为收点。 多段图的最短路径问题,是求从源点s 到达收点t 的最小花费的通路 一、顶点编号: 根据多段图的k 个不相交的子集i V ,把多段图划分为k 段,每一段包含顶点的一个子集。 把顶点集合V 中的所有顶点,按照段的顺序进行编号。 子集中的顶点互不邻接,它们之间的相互顺序无关紧要。 顶点个数为n ,顶点s 的编号为0,则收点t 的编号为1-n , 对E 中的任何一条边),(v u ,顶点u 的编号小于顶点v 的编号。 二、决策过程 数组元素][cos i t :存放顶点i 到达收点t 的最小花费 数组元素][i path :存放顶点i 到达收点t 的最小花费通路上的前方顶点编号 数组][n route :存放从源点s 出发,到达收点t 的最短通路上的顶点编号 第一阶段,确定第1-k 段的所有顶点到达收点t 的花费最小的通路。 第二阶段,用第一阶段的信息,确定第2-k 段的所有顶点到达收点t 的花费最小的通路。 如此依次进行,直到最后确定源点s 到达收点t 的花费最小的通路。 最后,从源点s 的path 信息中,确定它的前方顶点编号1p , 从1p 的path 信息中,确定1p 的前方顶点编号2p , 如此递推,直到收点t 。 动态规划函数: }][cos {min ][cos j t c i t ij n j i +=≤< (6.2.1) n j i j j t c i path ij ≤<+=最小的使][cos ][ (6.2.2) 三、步骤:(n 为顶点个数) 1. 对所有的n i i <≤0,,把][cos i t 初始化为最大值,][i path 初始化为-1;]1[cos -n t 初始化为0; 2. 令2-=n i ; 3. 根据(6.2.1)式和(6.2.2)式计算][cos i t 和][i path ; 4. 1-=i i ,若0≥i ,转3;否则,转5; 5. 令0=i ,0][=i route ; 6. 如果1][-=n i route ,算法结束;否则,转7; 6 7. 1+=i i ,]]1[[][-=i route path i route ;转6; 例6.2 求解图6.3所示的最短路径问题。 图6.3 动态规划方法求解多段图的例子 (i 表示顶点编号) 8=i :303]9[cos ]8[cos 89=+=+=t c t 9]8[=path 7=i :707]9[cos ]7[cos 79=+=+=t c t 9]7[=path 6=i :8}35,76{min }]8[cos ,]7[cos {min ]6[cos 6867=++=++=t c t c t 8]6[=path 5=i :9}36,78{min }]8[cos ,]7[cos {min ]5[cos 5857=++=++=t c t c t 8]5[=path 4=i :9}36,75{min }]8[cos ,]7[cos {min ]4[cos 4847=++=++=t c t c t 8]4[=path 3=i :13}87,94{min }]6[cos ,]5[cos {min ]3[cos 3635=++=++=t c t c t 5]3[=path 2=i :]}6[cos ,]5[cos ,]4[cos ,]3[cos {min ]2[cos 26252423t c t c t c t c t ++++= 14}88,97,96,131{min =++++= 3]2[=path 1=i :15}96,99{min }]5[cos ,]4[cos {min ]1[cos 1514=++=++=t c t c t 5]1[=path 0=i :}]3[cos ,]2[cos ,]1[cos {min ]0[cos 030201t c t c t c t +++= 15}133,141,154{min =+++= 2]0[=path 0]0[=route 2]0[]]0[[]1[===path route path route 3]2[]]1[[]2[===path route path route 5]3[]]2[[]3[===path route path route =path path route 8 = route ]4[= ]]3[ [ ]5[ route =path route = path ]]4[ 9 ]8[ [ ]5[= 最后,得到最短的路径为0,2,3,5,8,9,费用是15。 6.2.2 多段图动态规划算法的实现 struct NODE { /* 邻接表结点的数据结构 */ int v_num; /* 邻接顶点的编号 */ Type len; /* 邻接顶点与该顶点的费用 */ struct NODE *next; /* 下一个邻接顶点 */ }; struct NODE node[n]; /* 多段图邻接表头结点 */ Type cost[n]; /* 在阶段决策中,各个顶点到收点的最小费用 */ int route[n]; /* 从源点到收点的最短路径上的顶点编号 */ int path[n]; /* 在阶段决策中,各个顶点到收点的最短路径上的前方顶点编号 */ 算法6.1多段图的动态规划算法 输入:多段图邻接表头结点node[],顶点个数n 输出:最短路径费用,最短路径上的顶点编号顺序route[] 1. template 2. #define MAX_TYPE max_value_of_Type 3. #define ZERO_TYPE zero_value_of_Type 4. Type fgraph(struct NODE node[],int route[],int n) 5. { 6. int i; 7. struct NODE *pnode; 8. int *path = new int[n]; 9. Type min_cost,*cost = new Type[n]; 10. for (i=0;i 11. cost[i] = MAX_TYPE; path[i] = -1; rouet[i] = 0; 12. } 13. cost[n-1] = ZERO_TYPE; 14. for (i=n-2;i>=0;i--) { 15. pnode = node[i]->next; 16. while (pnode!=NULL) { 17. if (pnode->len+cost[pnode->v_num] 18. cost[i] = pnode->len + cost[pnode->v_num]; 19. path[i] = pnode->v_num; 6 6 20. } 21. pnode = pnode->next; 22. } 23. } 24. i = 0; 25. while ((route[i]!=n-1)&&(path[i]!=-1)) { 26. i++; 27. route[i] = path[route[i-1]]; 28. } 29. min_cost = cost[0]; 30. delete path; deleye cost; 31. return min_cost; 32. } 时间复杂性:)(m n +Θ 10~13行的初始化,花费)(n Θ时间。 14~23行局部决策,假定图的边数为m ,则花费时间为)(m n +Θ。 24~28行形成最优决策序列,若多段图分为k 段,花费)(k Θ时间。 空间复杂性是)(n Θ。 6.3 资源分配问题 资源总数为r ,工程个数为n 。给每项工程投入的资源不同,所获得的利润也不同。要求把总数为r 的资源,分配给n 个工程,以获得最大利润的分配方案。 6.3.1 资源分配的决策过程 一、目标函数和约束方程 资源r 划分为m 个相等的部分,每份资源为m r /,m 为整数。 利润函数m x n i x G i ≤≤≤≤0,1,)(: x 份资源分配给第i 个工程所得到的利润,已知 分配m 份资源给所有工程,所得到的利润总额为: m x x G m G n i i i n i i == ∑∑==1 1 ) ()( 使)(m G 最大的i x 分配方案:),,,(21n x x x 二、决策过程 各个工程按顺序编号, 阶段划分: 6 )(x f i :把x 份资源分配给前i 个工程时,所得到的最大利润, )(x d i :使)(x f i 最大时,分配给第i 个工程的资源份额。 在第一阶段,只把x 份资源分配给第一个工程,有: m x x x d x G x f ≤≤? ?? ==0)()()(111 (6.3.1) 在第二阶段,只把x 份资源分配给前面两个工程,有: x z m x z x f x d z x f z G x f z ≤≤≤≤? ?? =-+=0,0)()(})()({max )(22122达最大的使 一般的,在第i 阶段,把x 份资源分配给前面i 个工程,有: x z m x z x f x d z x f z G x f i i i i z i ≤≤≤≤? ?? =-+=-0,0)()(})()({max )(1达最大的使 (6.3.2) 令第i 阶段的最大利润为i g ,则: })(,,)1({max m f f g i i i = (6.3.3) 设i q 是使i g 达最大时,分配给前面i 个工程的资源份额,则: x x f q i i 达最大的使)(= (6.3.4) 在每个阶段,把所得到的所有局部决策值)(x f i ,)(x d i ,i g ,i q 保存起来。最后,在第n 阶段结束之后,令全局的最大利润为optg ,则: },,{max 1n g g optg = (6.3.5) 在全局最大利润下,所分配工程项目的最大编号(即所分配工程项目的最大数目)为k ,则: i g k i 最大的使= (6.3.6) 分配给前面k 个工程的最优份额为: i i q g optx 相对应的与最大的= (6.3.7) 分配给第k 个工程的最优份额为: )(optx d optq k k = 分配给其余1-k 个工程的剩余的最优份额为: )(optx d optx optx k -= 由此回溯,得到分配给前面各个工程的最优份额的递推关系式: 1,,1,) ( -=? ?? -==k k i optq optx optx optx d optq i i i (6.3.8) 由上面的决策过程,可以把求解资源分配问题,划分为下面四个步骤: 6 1. 按(6.3.1)(6.3.2)式,对各个阶段i ,各个不同份额x 的资源,计算)(x f i 及)(x d i ; 2. 按(6. 3.3)(6.3.4)式,计算各个阶段的最大利润i g ,及获得此最大利润的分配份额i q ; 3. 按(6.3.5)(6.3.6) (6.3.7)式,计算全局的最大利润optg ,总的最优分配份额optx ,及编号最大的工程项目k ; 4. 按(6.3.8)式递推计算各个工程的最优分配份额。 例6.3 有8个份额的资源,分配给3个工程,其利润函数如下: x 0 1 2 3 4 5 6 7 8 )(1x G 0 4 26 40 45 50 51 52 53 )(2x G 0 5 15 40 60 70 73 74 75 )(3x G 5 15 40 80 90 95 98 100 求资源的最优分配方案。 解 在第一阶段,只把资源的份额分配给第一个工程,由(6.3.1)式,有: x 0 1 2 3 4 5 6 7 8 )(1x f 0 4 26 40 45 50 51 52 53 )(1x d 1 2 3 4 5 6 7 8 其次,把资源的份额分配给前面两个个工程,当0=x ,显然有: 0)0(2=f ,0)0(2=d ; 当1=x ,由(6.3.2)式有: 5)5,4(max ))0()1(,)1()0((max )1(12122==++=f G f G f 1)1(2=d 当2=x ,有: 26)15,9,26(max ))0()2(,)1()1(,)2()0((max )2(1212122==+++=f G f G f G f 0)2(2=d 类似地计算8,,4,3 =x 时的)(2x f 及)(2x d 的值,有: x 0 1 2 3 4 5 6 7 8 )(2x f 0 5 26 40 60 70 86 100 110 )(2x d 1 4 5 4 4 5 同样,计算出)(3x f 及)(3x d 的值,有: x 1 2 3 4 5 6 7 8 6 )(3x f 0 5 26 40 80 90 106 120 140 )(3x d 1 4 5 4 4 4 第二步,按(6.3.3)(6.3.4)式,求各个阶段的最大利润,及在此利润下的分配份额,有: 531=g 1102=g 1403=g 81=q 82=q 83=q 第三步,按(6.3.5)(6.3.6) (6.3.7)式,计算全局的最大利润optg ,最大的工程数目、及总的最优分配份额,有: 140=optg 8=optx 3=k 第四步,按(6.3.8)式计算各个工程的最优分配份额,有: 4)8()(333===d optx d optq 4483=-=-=optxq optx optx 4)4()(222===d optx d optq 0442=-=-=optxq optx optx 0)0()(111===d optx d optq 最后的决策结果:分配给第2、3工程各4个份额,可得最大利润140。 6.3.2 资源分配算法的实现 数据结构。下面的数据用于算法的输入: int m; /* 可分配的资源份额 */ int n; /* 工程项目个数 */ Type G[n][m+1]; /* 各项工程分配不同份额资源时可得到的利润表 */ 下面的数据用于算法的输出: Type optg; /* 最优分配时所得到的总利润 */ int optq[n]; /* 最优分配时各项工程所得到的份额 */ 下面的数据用于算法的工作单元: Type f[n][m+1]; /* 前i 项工程分配不同份额资源时可得到的最大利润 */ int d[n][m+1]; /* 使f[i][x]最大时,第i 项工程分配的份额 */ Type g[n]; /* 只分配给前i 项工程时,可得到的最大利润 */ int q[n]; /* 只分配给前i 项工程时,第i 项工程最优分配份额 */ int optx; /* 最优分配时的资源最优分配份额 */ int k; /* 最优分配时的工程项目的最大编号 */ 算法6.2资源分配算法 输入:工程项目个数n, 可分配的资源份额m, 各项工程分配不同份额资源时可得到的利润表G[][] 输出:最优分配时所得到的总利润optg, 最优分配时各项工程所得到的份额optq[] 1. template 2. Type allot_res(int n,int m,Type G[][],int optq[]) 3. { 4. int optx,k,i,j,s; 5. int *q = new int[n]; /* 分配工作单元 */ 6. int (*d)[m+1] = new int[n][m+1]; 7. Type (*f)[m+1] = new Type[n][m+1]; 8. Type *g = new Type[n]; 9. for (j=0;j<=m;j++) { /* 第一个工程的份额利润表 */ 10. f[0][j] = G[0][j]; d[0][j] = j; 11. } 12. for (i=1;i 13. f[i][0] = G[i][0] + f[i-1][0]; 14. d[i][0] = 0; 15. for (j=1;j<=m;j++) { 16. f[i][j] = f[i][0]; d[i][j] = 0; 17. for (s=0;s<=j;s++) { 18. if (f[i][j] 19. f[i][j] = G[i][s] + f[i-1][j-s]; 20. d[i][j] = s; 21. } 22. } 23. } 24. } 25. for (i=0;i 24. g[i] = f[i][0]; q[i] = 0; 25. for (j=1;j<=m;j++) { 26. if (g[i] 27. g[i] = f[i][j]; q[i] = j; 28. } 29. } 30. } 31. optg = g[0]; optx = q[0]; k = 0; 32. for (i=1;i 33. if (optg 6 34. optg = g[i]; optx = q[i]; k = i; 35. } 36. } 37. if (k 38. for (i=k+1;i 39. optq[i] = 0; 40. for (i=k;i>=0;i--) { /* 给最大编号之前的工程项目分配份额 */ 41. optq[i] = d[i][optx]; 42. optx = optx – optq[i]; 43. } 44. delete q; delete d; /* 释放工作单元 */ 45. delete f; delete g; 46. return optg; /* 返回最大利润 */ 47. } 时间复杂性:) Θ (2 n m 9~11行执行一个循环,花费) Θ时间; (m 12~24行执行一个三重循环,花费) m n nΘ + -; = m ( m 2/)1 ( (2 )1 25~30行花费) Θ时间; (m n 31~36行花费) Θ时间; (n 空间复杂性是) Θ。 n (m 6.4 设备更新问题 设备每年的运转都可为公司创造利润收入, 设备的性能随使用年限的增加而变坏,导致收入减少,维修费增加,利润下降。 设备的更新,需付出一笔经费,但可增加利润收入。 设备的更新问题是确定设备的最优更新策略,使得在一个确定期限里,为公司创造最大的利润。 6.4.1 设备更新问题的决策过程 设备更新问题的有关数据如表6.1所示。 I = 0列,表明现有设备的有关数据;I = 1列,表示第一年购买的设备的有关数据 其余类推; 使用年限:第0列:当年的有关数据,第一列:使用一年后的有关数据,其余类推; 利润、维修费用、更新费用:在第i年购买的设备,使用了j年后,可以创造的利润、必须付出的维修费用、以及进行更新时需要付出的费用。 6 6 表6.1 设备更新的有关数据 变量和函数: )(t r k 第k 年购买的设备使用了t 年后,在第t k i +=年所创造的利润; )(t m k 第k 年购买的设备使用了t 年后,在第t k i +=年所付出的维修费用; )(t u k 第k 年购买的设备使用了t 年后,在第t k i +=年进行更新的费用; )(t buy i 使用了t 年后的设备, 第i 年被更新,在第i 年及其以后的年份所创造的总利润(在今后的年份里,设备还可能被更新); )(t rem i 使用了t 年后的设备, 第i 年继续使用,在第i 年及其以后的年份所创造的总利润(在今后的年份里,设备还可能被更新); )(t f i 使用了t 年后的设备,在第i 年及其以后的年份里,所创造的总利润; )(t x i 对使用了t 年后的设备,在第i 年所作出的更新设备、或保留继续使用的决策; i p 以现有设备为基础,在第i 年作出的更新设备、或保留继续使用的最优决策; 现有设备已经使用了D 年。则设备更新问题表示为在今后n 年里,使得)(1D f 最大的最优决策序列i p ,n i ,,2,1 =。 对使用了t 年后的设备,第i 年决定更新,则利润函数如下: ???≥+--<+--=++-i t f t u m r i t f t u m r t buy i i i i t i i i i ) 1()()0()0() 1()()0()0()(101(6.4.1) 如果第i 年决定保留继续使用,则有利润函数如下: ???≥++-<++-=++--i t t f t m t r i t t f t m t r t rem i i t i t i i ) 1()()() 1()()()(1001 (6.4.2) 于是,可以定义如下的规划函数: ))(),((max )(t rem t buy t f i i i = (6.4.3) ?? ?<≥=) ()() ()()(t rem t buy false t rem t buy true t x i i i i i (6.4.4) 假定,所要决策的年限为n 年,对所有的t ,令 0)(1=+t f n (6.4.5) 阶段划分:把n 年划分为n 个阶段。 第n 阶段,设备的使用年限t 为D n n +--1,1,,2,1 。计算)(t f n ,确定)(t x n ;