动态规划算法的递归实现,由于被多次的计算,所以时间复杂度比较高,想的办法是每个子问题只算一次,后面用到的时候,把那个值拿过来就可以把时间降下来,这个就是动态规划算法的迭代实现。
文章目录
一、迭代计算的关键
- 每个子问题只计算一次
- 迭代过程
(1)从最小的子问题算起
(2)考虑计算顺序,以保证后面用到的值前面已经计算好
(3)存储结构保存计算结果——备忘录 - 解的追踪
(1)设计标记函数标记每步的决策
(2)考虑根据标记函数追踪解的算法
当最后优化函数算出来,问题的解是另外一件事情,优化函数比如矩阵链问题,只是运算次数达到最小了,但是括号加的位置这个是问题的解,所以要通过标记函数实现
二、矩阵链乘法不同子问题
长度1:只含1个矩阵,有n个子问题
(不需要计算)
长度2:含2个矩阵,n-1个子问题
长度3:含3个矩阵,n-2个子问题
…
长度n-1:含n-1个矩阵,2个子问题
长度n:原始问题,只有1个
三、矩阵链乘法迭代顺序
长度为1:初值,m[i, i] = 0
长度为2:1…2, 2…3, 3…4, … , n-1…n
长度为3:1…3, 2…4, 3…5, … , n-2…n
…
长度为n-1:1…n-1, 2…n
长度为n:1…n
四、n=8的子问题计算顺序
一共是八个矩阵A1…A8,初值不考虑了,
1、长度为2的子问题:
(A1,A2),(A2,A3),…,(A7,A8)
2、长度为3的子问题:
(A1,A2,A3),(A2,A3,A4),…,(A6,A7,A8)
3、…
4、原始问题:
(A1,A2,A3,A4,A5,A6,A7,A8)
五、代码实现
1. 令所有的m[i,i]初值为0
2. for r←2 to ndo // r为链长
3. for i←1 to n−r+1 do // 左边界i
4. j←i+r−1 // 右边界j
5. m[i,j]←m[i+1,j]+pi−1pi pj//k=i
6. s[i,j]←i //记录k
7. for k←i+1 to j−1 do // 遍历k
8. t←m[i,k]+m[k+1,j]+pi−1 pkpj
9. if t<m[i,j]
10. then m[i,j]←t //更新解
11. s[i,j]←k
m记录的是所有子问题的最少乘法次数,s记录的是分界的位置
六、时间复杂度
- 根据伪码:行2, 3, 7 都是O(n),循环
执行O(n3)次,内部为O(1)
W(n) = O(n3) - 根据备忘录:估计每项工作量, 求和.
子问题有O(n2)个,确定每个子问题的
最少乘法次数需要对不同划分位置比
较,需要O(n)时间.
W(n) = O(n3)
•追踪解工作量O(n),总工作量O(n3)
七、实例
行列参数在P里面,矩阵个数为5个矩阵,这5个矩阵的行列号都可以有参数列出来
1、输入:
P = < 30, 35, 15, 5, 10, 20 >,
n = 5
2、矩阵链:
A1A2A3A4A5,其中
A1:30×35,A2:35×15,A3:15×5,
A4:5×10,A5:10×20
3、备忘录:
存储所有子问题的最小乘法
次数及得到这个值的划分位置.