【问题标题】:Dynamic programming from cormen's bookcormen 书中的动态编程
【发布时间】:2017-02-19 19:45:39
【问题描述】:
在 cormen 的“算法简介”第 15 章:动态规划中阅读动态规划时,我遇到了这种说法
在开发动态规划算法时,我们遵循以下顺序
四个步骤:
-
描述最优解的结构。
-
递归定义最优解的值。
-
计算最优解的值,通常以自下而上的方式。
-
根据计算的信息构造一个最优解。
步骤 1-3 构成了问题的动态规划解决方案的基础。要是我们
只需要最优解的值,而不需要解本身,那么我们
可以省略第 4 步。当我们执行第 4 步时,我们有时会维护额外的
步骤 3 中的信息,以便我们可以轻松构建最佳解决方案。
我不明白第 3 步和第 4 步的区别。
计算最优解的值
和
构造最优解。
我希望通过进一步阅读来理解这一点,但未能理解。
有人可以举个例子帮助我理解这一点吗?
【问题讨论】:
标签:
algorithm
dynamic-programming
【解决方案1】:
假设我们使用动态规划来计算 [1,3,4,6,10] 中是否存在总和为 9 的子集。
第 3 步的答案是值,在本例中为“TRUE”。
第 4 步的答案是计算总和为 9 的实际子集,在本例中为“3+6”。
【解决方案2】:
在动态编程中,我们大多数时候都会得到一个巨大的结果哈希值。然而,最初它只包含从第一个、最小、最简单(底部)情况获得的结果,通过使用这些初始结果并在它们之上进行计算,我们最终合并到目标。此时散列中的最后一项大部分时间都是目标(步骤 3 完成)。然后我们必须对其进行处理以获得所需的结果。
一个完美的例子是找到一个目标的最小立方体数。目标是 500,我们应该得到 [5,5,5,5],或者如果目标是 432,我们必须得到 [6,6]。
所以我们可以如下在JS中实现这个任务;
function getMinimumCubes(tgt){
var maxi = Math.floor(Math.fround(Math.pow(tgt,1/3))),
hash = {0:[[]]},
cube = 0;
for (var i = 1; i <= maxi; i++){
cube = i*i*i;
for (var j = 0; j <= tgt - cube; j++){
hash[j+cube] = hash[j+cube] ? hash[j+cube].concat(hash[j].map(e => e.concat(i)))
: hash[j].map(e => e.concat(i));
}
}
return hash[tgt].reduce((p,c) => p.length < c.length ? p:c);
}
var target = 432,
result = [];
console.time("perf:");
result = getMinimumCubes(target);
console.timeEnd("perf:");
console.log(result);
所以在这段代码中,hash = {0:[[]]}, 是第 1 步;最终准备 hash[tgt] 的嵌套 for 循环实际上是第 3 步,而返回阶段的 .reduce() 函子是第 4 步,因为它形成了哈希的最后一项 (hash[tgt]) 以提供我们想要的结果通过过滤出所有结果中与目标值相加最短的结果。
对我来说,第 2 步有点毫无意义。不是因为提到递归,而是因为意义。此外,我从未使用过也没有见过动态编程中的递归方法。最好使用while 或for 循环来实现。