- 最优子结构:原问题的最优解包含子问题的最优解
- 重叠子问题:用来求解原问题的算法能重复地解相同的子问题而不产生新的子问题
矩阵连乘
- 两矩阵Mi和Mi+1,维数分别是pi×pi+1和pi+1×pi+2,则Mi⋅Mi+1需要进行pi×pi+1×pi+2次乘法
- n个矩阵连乘M1⋅M2⋅⋯⋅Mn,加括号使得乘法运算次数最少
设M1⋅M2⋅⋯⋅Mn最少的连乘次数为f(1,n),那么它显然是从所有位置切开分为左右两部分相乘的方案中最优的那一个,即包含子问题的最优解:
f(i,j)=max{f(i,k−1)+f(k,j)+pipkpj+1∣i<k≤j}
对于f(1,n),其重叠子问题的集合为:
{f(i,j)∣1≤i≤j≤n}
共n(n+1)/2个,因此空间复杂度为O(n2);每个f(i,j)都需要从i到j计算一遍f(i,k−1)+f(k,j)+pipkpj+1,因此时间复杂度为O(n3)。
钢条切割
切割销售一段长度为n的钢条,对于切出的每个长度i都有一个销售价格pi,问如何切使收益最大。
若设f(x)为长度为n钢条切割后的最大收益,那么它包含子问题的最优解:
f(x)=max{f(x−i)+pi∣1≤i≤x}
对于f(n),其重叠子问题的集合为:
{f(x)∣1≤x≤n}
共n个,因此时间复杂度为O(n)。
最长公共子序列(LCS)
- X=x1x2…xm, 若1≤i1<i2<⋯<ik≤m,使Z=z1z2…zk=xi1xi2…xik, 称Z是X的子序列
- Z是序列X与Y的公共子序列:Z既是X的子序列又是Y的子序列
若设LCS(Xm,Yn)是Xm=x1x2…xm和Yn=y1y2…yn的最长公共子序列,那么它包含子问题的最优解:
LCS(Xm,Yn)={LCS(Xm−1,Yn−1)+1max{LCS(Xm−1,Yn),LCS(Xm,Yn−1)}xm=ynxm=yn
对于LCS(Xm,Yn),其重叠子问题集合为:
{LCS(Xi,Yj)∣1≤i≤m,1≤j≤n}
共mn个,故时间复杂度为O(mn)。
最优二叉搜索树

若设w(i,j)=∑k=ijqk+∑k=i+1jpk

在一个二叉搜索树中,每一条边的权值都是其所连子树的所有元素的权值和,而每下一层搜索长度+1,因此以某个点为根的子树所产生的的平均搜索长度是其左右子树的概率×1加上总的概率×1:
因此以pk,k∈[i,j]为根的最优二叉树贡献的平均搜索长度c(i,j)为:
c(i,j)=w(i,j)+c(i,k−1)+c(k,j)
要找到这个最优二叉树c(i,j),即是找到最优的根节点k,它包含子问题的最优解:
c(i,j)=w(i,j)+min{c(i,k−1)+c(k,j)∣1<k≤j}

对于c(0,n),它的重叠子问题集合为:
{c(i,j)∣1≤i≤j≤n}
共n(n+1)/2个,因此空间复杂度为O(n2);每个c(i,j)都需要从i到j计算一遍c(i,k−1)+c(k,j),因此时间复杂度为O(n3)。
流水线作业调度问题

显然,在最优方案中:
- 两台机上上加工次序完全相同
- 若不然,某个任务需要等待其后执行的任务完成第二道工序才能执行,时间更长
- 第一道工序是无间断的
进而,此问题的搜索树是一个排列树,即确定任务的执行次序。
若设任务集合为S,开始执行时第二道工序还在执行其他任务,t时间后才能使用,设此情况下的最优调度花费的时间为T(S,t),如果此时最优方案是选择ai作为第一个执行的任务,那么:
T(S,t)={ai+T(∁S{i},bi)ai+T(∁S{i},bi+(t−ai))t≤ait>ai
进而找最优解T(S,t)就是找最优的ai的过程,其包含子问题的最优解:
T(S,t)=ai+min{T(∁S{i},bi+max{t−ai,0})∣i∈S}
重叠子问题的集合为:
{T(S,t∁NS)∣S⊆N}
相当于把N的每个非空子集都计算一次,共∑k=1nCnk=2n−1个,每次计算都要把S中的任务全扫一遍,时间复杂度O(n2n−1)。
进一步剪枝:Johnson法则
假定在T(S,t)中,前两个被执行的任务是ai和aj,那么:
T(S,t)=ai+min{T(∁S{i},bi+max{t−ai,0})∣i∈S}=ai+T(∁S{i},ti)=ai+aj+T(∁S{i,j},tij)ti=bi+max{t−ai,0}tij=bj+max{ti−aj,0}
而其中:
tij=bj+max{ti−aj,0}=bj+max{bi+max{t−ai,0}−aj,0}=bj+bi−aj+max{max{t−ai,0},aj−bi}=bj+bi−aj+max{t−ai,0,aj−bi}=bj+bi−aj−ai+max{t,ai,ai+aj−bi}
可以证明对于最优方案中的所有相邻任务ai,aj,min{bi,aj}≥min{bj,ai}必然成立:
反证法,若min{bi,aj}<min{bj,ai}
min{bi,aj}−min{bi,aj}max{−bi,−aj}ai+aj+max{−bi,−aj}max{ai+aj−bi,ai}max{t,ai+aj−bi,ai}max{t,ai+aj−bi,ai}tij<min{bj,ai}>−min{bj,ai}>max{−bj,−ai}>ai+aj+max{−bj,−ai}>max{ai+aj−bj,aj}≥max{t,ai+aj−bj,aj}≥max{t,ai+aj−bj,aj}≥tji
即如果不满足min{bi,aj}≥min{bj,ai},将ai,aj交换位置后更节约时间,进而T(S,t)也不是最优方案。
因此,在最优方案中必然有min{bi,aj}≥min{bj,ai}成立。
这个不等式给我们带来了一个剪枝方法:已选择的前一个任务为i,已知ai,bi,那么后一个任务j只能在满足min{bi,aj}≥min{bj,ai}的任务中选。进而·能通过剪枝降低算法复杂度。