第三章动态规划算法[]概要
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
for (int r = 2; r <= n; r++)
for (int i = 1; i <= n – r +1; i++) {
int j = i + r – 1;
(5) m[i][j] = m[i+1][j] + p[i–1]*p[i]*p[j];
(7)
//计算A[i, j] = A[i: i] A[i+1: j] s[i][j] = i; //记下断点i
不同计算顺序的差别
设矩阵A1, A2和A3分别为10×100, 100×5和 5×50的矩阵,现要计算A1A2A3 。
若按((A1A2)A3)来计算,则需要的数乘次数为 10×100×5 + 10×5×50 = 7500
若按(A1(A2 A3))来计算,则需要的数乘次数为 100 ×5 ×50+ 10×100×50 = 75000
第四章
动态规划
矩阵连乘问题
给定n个矩阵:A1, A2, …, An,其中Ai与Ai+1是 可乘的。确定一种连乘的顺序,使得矩阵连 乘的计算量为最小。
设A和B分别是p×q和q×r的两个矩阵,则乘 积C=AB为p×r的矩阵,计算量为pqr次数乘。
但是对于多于2个以上的矩阵连乘,连乘的顺 序却非常重要,因为不同的顺序的总计算量 将会有很大的差别。
for (int k = i + 1; k < j; k++) {
能第。(5此)步处与分第开(7是)步为 了能给否m合[i在][j一]赋起初? 值。
int t = m[i][k] + m[k+1][j] + p[i–1]*p[k]*p[j];
//对i<k<j, 逐个计算A[i, j] = A[i: k] A[k+1: j]
断开的,即A[1: n] = (A[1: k] A[k+1: n]),则 A[1: k]和A[k+1: n]也分别是最优解。 事实上,若A[1: k]的一个计算次序所需计算量 更少的话,则用此计算次序替换原来的次序, 则得到A[1: n]一个更少的计算量,这是一个矛 盾。同理A[k+1: n]也是最优解。 最优子结构性质:最优解的子结构也最优的。
建立递归关系
令m[i][j] , 1≤i, j≤n,为计算A[i, j] 的最少数乘 次数,则原问题为m[1][n]。
当i = j时,A[i, j]为单一矩阵, m[i][j] = 0;
当i<j时,利用最优子结构性质有:
m[i][j]
=
min{m[i][k]
i≤k<j
+
m[k+1][j]
+
pi–1pkpj}
k=1
n–1
n–1
= n +∑T(k) + ∑T(n–k)
k=1
k=1
n–1
= n + 2∑T(k)
k=1
可用数学归纳法证明T(n)≥2n–1 = Ω(2n)。
直接递归算法的时间复杂性随n的指数增长。
直接递归中有大量重复计算
直接递归中有大量重复计算,如A[1: 4]计算中:
1: 4
图中红框标出的
计算方式可依据递归式自底向上地进行。 注意到在此问题中,不同的有序对 (i, j)就对应
不同的子问题,因此不同的子问题个数个数最 多只有Cn2+ n = (n2)个。 这样便可以得到多项式时间的算法。
自底向上的计算
例如对于A1A2A3A4,依据递归式以自底向上的 方式计算出各个子问题,其过程如下: m[2][4] 例如其:中 m[1][3] = m[1][3] m[2][4] mim{nm[imm[]i[][[j[11]k]]=][[+12m]]m++i[nmmki≤+[[k23<1]]]j[[[33j]]]+++pppi00–pp1p12ppkp33 j} m[1][2] m[2][3] m[3][4] m[i][i+1] = pi–1pipi+1
后一种计算顺序的计算量竟是前者的10倍! 所以,求多个矩阵的连乘积时,计算的结合
顺序是十分重要的。
不同计算顺序的数量
设n个矩阵的连乘积有P(n)个不同的计算顺序。
先 由在 此第 可k得个出和关第于kP+(1n个)的矩递阵归之式间:将原矩阵序列 分成两个矩阵子序1 列,k=1,…,n =n;1 再分别 对 号两 ,个 便子 得P(序 到n) 列原= 完序全列234 加的n∑k=–括一11P(号种k),完P(最全n–后加k) 对 括n结 号>果 方1 加 式括 。
if (t < m[i][j]) {m[i][j] = t; s[i][j] = k;}
//记下较小的m[i][j]及相应的断点k
}}}
MatrixChain的运行举例
m[1][1] m[2][2] m[3][3] m[4][4] m[i][i] = 0
消除重复的矩阵连乘算法
Void MatrixChain(int p, int n, int **m, int **s)
பைடு நூலகம்
{ for (int i = 1; i <= n; i++) m[i][i] = 0;
//将对角线元素赋值为零,即单个矩阵计算量为0
解此递归方程可得P(n) = C(n–1),其中
C(n) =
1 n+1
2n n
= Ω(4n/n3/2)
所以P(n)随n的增长呈指数增长。因而穷举搜 索法不是有效的算法。
分解最优解的结构
将矩阵连乘积AiAi+1…Aj记为A[i: j]。 若A[1: n] 的一个最优解是在矩阵Ak和Ak+1处
其中矩阵Ai ,1≤i≤n,的维数为pi–1×pi。
根据此递归式就可以直接用递归程序来实现。
直接递归的时间复杂性
根据前面的递归式不难得出的时间复杂性为
n–1
T(n) ≥ 1 + ∑(T(k) + T(n–k) + 1)
k=1 n–1
= 1 + (n – 1) +∑(T(k) + T(n–k))
都是重复计算。
1: 2
3: 4
1: 1 2: 4
1:1 2: 2 3: 3 4: 4
1: 3 4: 4
2: 2 3: 4 2: 3 4: 4
1: 1 2: 3 1: 2 3: 3
3: 3 4: 4 2: 2 3: 3
2: 2 3: 3 1: 1 2: 2
消除重复的计算
要消除重复计算,可在在计算过程中保存已解 决的子问题的答案。这样,每个子问题只计算 一次,而在后面需要时只要简单查一下,从而 避免重复计算。