动态规划
和分治法一样,动态规划是通过组合子问题的解而解决整个问题的。分治法算法是指将问题划分成一些独立的子问题,递归地求解各子问题,然后合并子问题的解而得到原问题的解。动态规划适用于子问题不是独立的情况,也就是各子问题包含公共的子子问题。动态规划算法对每个子子问题只求解一次,将其结果保存在一张表中,从而避免每次遇到各个子问题时重新计算答案。
动态规划通常应用于最优化问题,此类问题可能有很多种可行解,我们希望找出一个具有最优值的解,可能存在多个取最优值的解
动态规划算法的设计可以分为如下4个步骤:
1 描述最优解的结构
2 递归定义最优解的值
3 按自底向上的方式计算最优解的值
4 由计算出的结果构造一个最优解
装配线调度:
条件:
2条装配线,每一条装配线上有n个装配站,编号为j=1···n,顺序相同的装配站有相同的功能,但是时间不同,
我们把在装配站S(i,j)上所需的装配时间记为a(i,j),底盘进入装配线i的进入时间为e(i),装配完的汽车离开装配线i的离开时间为x(i)
把已经通过装配站S(i,j)的一个底盘从装配线i移走所花的时间为t(i,j),相同的装配线移动没有开销
问题:
要确定在装配线1内选择哪些站以及在装配线2内选择哪些站,以使汽车通过工厂的总时间最小
步骤一:通过工厂最快路线的结构
寻找通过任一条装配线上的装配站j的最快路线,我们解决它的子问题,即寻找通过两条装配线上的装配站j-1的最快路线
步骤二:一个递归的解
我们的最终目标是确定地盘通过工厂的所有路线的最快时间,记为f*。
f*=min(f1[n]+x1,f2[n]+x2)
第一个站点:
f1[1]=e1+a(1,1)
f2[1] = e2+a(2,1)
中间站点2····n:
f1[j]=min(f1[j-1]+a(1,j),f2[j-1]+t(2,j-1)+a(1,j))
f2[j]=min(f2[j-1]+a(2,j),f1[j-1]+t(1,j-1)+a(2,j))
递归公式:
f1[j]={e1+a(1,1) 如果j=1
{min(f1[j-1]+a(1,j),f2[j-1]+t(2,j-1)+a(1,j)) 如果j>=2
f2[j]={e2+a(2,1) 如果j=1
{min(f2[j-1]+a(2,j),f1[j-1]+t(1,j-1)+a(2,j)) 如果j>=2
步骤三:计算最快时间
如果直接计算,会有很大的效率问题
在递归中,可以以不同的顺序来计算值,能做的更好,参考算法导论195页,fastest-way算法
这种算法计算过程就是在表格中填入记录,对于下一个数,只需要简单地查表来确定它们的值。
步骤四:构造通过工厂的最快路线
动态规划基础:
采用动态规划方法的最优化问题中的两个要素:最优子结构和重叠子问题
还要分析一种不同的方法:备忘录,以充分利用重叠子问题性质
最优子结构:
用动态规划求解优化问题的第一步是描述最优解的结构,
如果问题的一个最优解中包含了子问题的最优解,则该问题具有最优子结构,当一个问题具有最优子结构时,动态规划可能会适用
在找寻最优子结构时,可以遵循一个共同的模式:
1 问题的一个解可以是做一个选择
2 假设对一个给定的问题,已知的是一个可以导致最优解的选择,不必关心如何确定这个选择,尽管假定它是已知的
3 在已知这个选择后,要确定哪些子问题会随之发生,以及如何最好地描述所得到的子问题空间
4 利用一种“剪贴技术”,来证明在问题的一个最优解中,使用的子问题的解本身也必须是最优的。
为了描述子问题空间,可以遵循这样一条有效地经验规则,就是尽量保持这个空间简单,然后在需要时再扩充它
最优子结构在问题域中以两种方式变化:
1 有多少个子问题被使用在原问题的一个最优解中,
2 在决定一个最优解中使用哪些子问题时有多少个选择
一个动态规划算法的运行时间依赖于连个因素的乘积:子问题的总个数和每一个子问题中有多少中选择
动态规划以自底向上的方式来利用最优子结构:先找到子问题的最优解,解决子问题,然后找到问题的一个最优解
重叠子问题:
适用于动态规划求解的最优化问题必须具有的第二个要素是子问题的空间要“很小”,也就是用来解原问题的递归算法可反复地解同样的子问题,而不是总在产生新的子问题。
重构一个最优解,
做备忘录
动态规划有一种变形,它既具有通常的动态规划方法的效率,又采用了一种自顶向下的策略,其思想就是备忘原问题的自然但低效
的递归算法,像在通常的动态规划中一样,维护了一个记录子问题解的表,但有关填表动作的控制结构更像递归算法
最长公共子序列
问题:给定了两个序列X,Y,希望找出X和Y的最长公共子序列(LCS),子序列可以是不连续的,和最长公共字串不同
步骤1 描述一个最长公共子序列

步骤2 一个递归解

步骤3 计算LCS的长度



步骤4 构造一个LCS


浙公网安备 33010602011771号