理念
切分子问题,同时记住已经解决过的子问题的解,以便解决整个问题。
适用场景: 重叠子问题,和最优子结构
下面以例子来解释
钢管切割问题
本题是算法导论上的题目具体问题不描述,直接复制粘贴来:
Serling公司购买长钢条,将其切割为短钢条出售。切割工序本身没有成本支出。公司管理层希望知道最佳的切割方案。假定我们知道Serling公司出售一段长为i英寸的钢条的价格为pi(i=1,2,…,单位为美元)。钢条的长度均为整英寸。图15-1给出了一个价格表的样例。

钢条切割问题是这样的:给定一段长度为n英寸的钢条和一个价格表pi(i=1,2,…n),求切割钢条方案,使得销售收益rn最大。注意,如果长度为n英寸的钢条的价格pn足够大,最优解可能就是完全不需要切割。
暴力递归解法
先来个公式: rn = Max(pi, r(n-i)) 0 =< i <= n
这个公式是怎么得到的?
r2
function CutRod(pn=[], n) {if (n === 0) return 0;let q = pn[0];let f = 0;for(let i = 1 ; i < n ; i++){f = Math.max(pn[n-1], CutRod(p, i) + CutRod(p, n-i));q = Math.max(f, q);}return q}
动态规划-自顶向下
此处又分为两种自顶向下的递归,只是带了备忘记录。比纯暴力解法省下了很多计算
function MemoizedCutRodAux(pn, n, r) {if(r[n]) return r[n]let q = -1;if(n === 0) q = 0;else {for(let i = 1 ; i < n ; i++){let tmp = pn[i-1] + MemoizedCutRodAux(pn, n-i, r)if( q < tmp) q = tmp}}r[n] = q;return r[n]}function MemoizedCutRod(pn=[], n) {let r = []for(let i = 0 ; i < n ; i ++) {r[i] = -1}return MemoizedCutRodAux(pn, n, r)}
动态规划-自底向上
function BottomUpCutRod(pn=[], n) {let r = new Array(n)r[0] = 0for(let i = 1 ; i < n ; i ++) {let q = -1for(let j = 1; j < i; j ++) {let tmp = p[j] + r[i - j];if(q > tmp) q = tmp}r[i] = q}return r[n]}
