学好动态规划三步曲

Posted 大数据与计算智能

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学好动态规划三步曲相关的知识,希望对你有一定的参考价值。

动态规划,也是基于递归算法,是其高明之处在于利用备忘录的方法来记录已经求解过子问题的解避免对子问题的重复计算。而这些备忘录通常一维数组或者二维数组实现,以保存子问题的解

下面介绍设计动态规划算法的三个步骤

一步:定义子问题。这个子问题通常由问题参数来决定,子问题解决了,则原问题也迎刃而解。而子问题的最优目标函数值,由数组来保存,通常问题参数有几个,数组就是几维的。

1. Fibonacci序列 考虑子问题Fibonacci序列F(i)求序列i个数的值涉及一个问题参数i,因此可以用一维数组F[i]来保存子问题F(i)的值。

2. 装配线调度问题 考虑子问题F1(j)(1条装配线的第j个站点)汽车底盘从进厂点到装配点S1[j]的最短装配时间问题。涉及1个问题参数j,因此,可以用一维数组F1[j]来保存子问题F1(j)的最快完成时间。类似考虑子问题F2(j)

3. 矩阵链乘积问题 考虑子问题m(i,j)如何对矩阵链Ai,Ai+1,...,Aj的乘积加括号,使得乘法次数最少。涉及两个问题参数i,j,因此,可以用二维数组m[i,j]来表示子问题m(i,j)的最小乘法次数。

4. 最长公共子序列 考虑子问题C(i,j)给定两个子序列Xi=<x1,x2,...,xi>Yj=<y1,y2,...,yj>,寻找它们的最长公共子序列。涉及两个参数i,j,因此可以用二维数组C[i,j]来表示最长公共子序列的长度。

5. 0/1背包问题 令子问题V(i,w)表示求给定物品集合{1,2,...,i},背包载重量为最大价值问题涉及两个参数i,w,因此可以用二维数组V[i,w]来表示子问题V(i,w)的最大价值。

第二步:问题分解。原问题求解复杂,我们可以将原问题分解成若干个子问题,而且子问题与原问题相似,找出原问题与子问题之间的递归关系式。

1.Fibonacci序列 子问题F(i)分解为两个子子问题F(i-1)F(i-2)

2.装配线调度问题 子问题f1(j)(1条装配线的第j个站点):如果j>1,到达点S1(j)有两种走法:

a) 从前一个装配点S1[j-1]直接传送到点S1[j]装配涉及子子问题f1(j-1)

b) 前一个装配点S2[j-1]装配后,传送到装配线1的装配点S1[j]装配涉及子子问题f2(j-1)

类似的考虑子问题f2(j)

3.矩阵链乘积问题 考虑子问题m(i,j)假设子问题m(i,j)最优加括号方式是把乘积在AkAk+1之间分开

AiAi+1...Aj=Ai...AkAk+1...Aj

子问题m(i,j)分成两个子子问题m(i,k)m(k+1,j)

4.最长公共子序列 子问题C(i,j)的划分:

1)如果xi=yj,则子问题划为一个子子问题C(i-1,j-1)

2)如果xiyj,则子问题C(i,j)为一个子子问题C(i,j-1)或者一个子子问题C(i-1,j)

5.0/1背包问题 子问题V(i,w)的划分有两种情况:

(1)如果wi>w则子问题V(i,w)划分为子子问题V(i-1,w)

(2)如果wiw则子问题V(i,w)分两种情况划分子问题:

a) 装进去,则子问题V(i,w)划分为一个子子问题V(i-1,w-wi)

b) 不装进去,则子问题V(i,w)划分为一个子子问题V(i-1,w)

第三步:最优子结构性质。导出子问题与子子问题目标值之间的关系式1.Fibonacci序列 子问题F(i)分解为两个子子问题F(i-1)F(i-2),递归关系是F(i)=F(i-1)+F(i-2)这里自然的递归方程,没有最优化目标函数值。

2.装配线调度问题 假定到点S1[j]最快装配路线

a) 如果是从前一个装配点S1[j-1]直接到点S1[j]则从进厂点到点S1[j-1]的装配路线p也一定是从进厂点到点S1[j-1]的最快装配路线。f1[j]=f1[j-1]+a1[j]

b) 如果是从前一个装配点S2[j-1]装配后,传送到装配线1的装配点S1[j]装配,则从进厂点到点S2[j-1]的装配路线p也一定是从进厂点到点S2[j-1]的最快装配路线。f1[j]=f2[j-1]+t2[j-1]+a1[j]

要计算经过点S1[j]的最短时间f1[j],只需从上述两种情况中,选最优的即可:f1[j]=min{f1[j-1]+a1[j],f2[j-1]+t2[j-1]+a1[j]}

类似的,要计算过点S2[j]的最短装配时间f2[j],只需计算

f2[j]=min{f2[j-1]+a2[j],f1[j-1]+t1[j-1]+a2[j]}

3.矩阵乘积问题 假设m(i,j)的一种最优完全括号化方式是把乘积在AkAk+1(ik<j)间分开,则其中子问题m(i,k)m(k+1,j)的加括号的方式也一定是最优的。即有m[i,j]=m[i,k]+m[k+1,j]+pi-1pkpj

事实上,我们不知道最优在哪里划分,划分的方式有j-i种,即k=i,i+1,...,j-1,因此,我们必须在j-i种划分中,选择使m[i,j]值最小的划分,因而可得递归方程

4.最长公共子序列 子问题C(i,j)的划分:

1)如果xi=yj,子问题划为为一个子子问题C(i-1,j-1)子问题C(i,j)的最优解里一定包含了子子问题C(i-1,j-1)的最优解,即一定有C[i,j]=C[i-1,j-1]+1

2)如果xiyj假设子问题C(i,j)的最优为一个子子问题C(i,j-1),则一定有C[i,j]=C[i,j-1]

假设最优划分为一个子子问题C(i-1,j)一定有C[i,j]=C[i-1,j]事实上,我们不知道那种划分好,所以选两种划分里,最优的划分,即

C[i,j]=max{C[i,j-1],C[i-1,j]}

5.0/1背包问题 子问题V(i,w)的划分有两种情况:

(1) 如果wi>w,则子问题V(i,w)的最优解里一定包括了子子问题V(i-1,w)的最优解,一定有V[i,w]=V[i-1,w-wi];

(2) 如果wiw,分两种情况情况进行讨论

a) 如果子问题V(i,w)的最优解是装进去wi,则子问题V(i,w)的最优解包括了子子问题V(i-1,w-wi)的最优解V[i,w]=V[i-1,w-wi]+vi;

b)如果不装进去,则子问题V(i,w)的最优解包括了子子问题V(i-1,w)的最优解

事实上,我们不知道a) b)两种情况,那种方式更优,因此做最优的决策:

V[i-1,w-wi]=max{V[i-1,w-wi]+vi,V[i-1,w]}

以上是关于学好动态规划三步曲的主要内容,如果未能解决你的问题,请参考以下文章

北大学霸总结的动态规划4步曲,仅这篇动归够了

分享经典的动态规划问题

分享经典的动态规划问题

算法萌新如何学好动态规划(第一弹)

文末福利算法萌新如何学好动态规划(第二弹)

前端程序员学好算法系列动态规划