【发布时间】:2011-12-11 02:35:34
【问题描述】:
典型的 Lisp 方言可以使用bottom-up "dynamic programming" 方法解决问题吗?
(请注意:我不是在谈论 “memoization”,据我所知,使用任何 Lisp 方言都是微不足道的。我真正谈论的是自下而上的动态编程,例如,您在其中构建数组,然后使用您刚刚介绍的元素来计算下一个元素。)
例如,使用动态规划,“0-1 背包”问题可以在伪多项式时间内解决任何其他方法都会失败的输入。
命令式(不完整)解决方案是:
for (int k = 1; k <= a.length; k++) {
for (int y = 1; y <= b; y++) {
if (y < a[k-1]) {
knap[k][y-1] = knap[k-1][y-1];
} else {
if (y > a[k-1]) {
knap[k][y-1] = Math.max(knap[k-1][y-1], knap[k-1][y-1-a[k-1]] + c[k-1]);
} else {
knap[k][y-1] = Math.max(knap[k-1][y-1], c[k-1]);
}
}
在各种 Lisp 方言中可以做到这一点吗?如果没有,为什么不呢?
【问题讨论】:
-
我不确定我是否理解这个问题; Lisps 中算法的规范实现几乎总是递归和“自下而上”的。
-
@Dave Newton:我可能不太清楚......我指的是“自下而上”,而不是维基百科关于动态编程的文章中的“自上而下”,其中“记忆化” (保存幂等方法/函数调用的结果以供以后重用)将是“自上而下”,而从底部开始工作将是“自下而上”。这两种方法都可以将一些问题减少到伪多项式时间。但在这种情况下我对 memoization 不感兴趣:我想知道我是否可以从“自下而上”构建,比如数组(我计算单元格 1,然后我使用单元格 1计算单元格 2 等)
-
是什么让你觉得在 Lisp 中不能做到这一点?
-
你认为 Lisp 是一种函数式语言吗?尽管您可以以那种风格使用它(尤其是 Scheme,由于尾递归优化),并且您可以用它的语法做很多强大和/或奇怪的事情,但它仍然只是一种具有可变状态的命令式语言,就像 C . 你可以将你的 C 代码基本上“逐字”翻译成 Lisp。
-
@CedricMartin:Common Lisp 是一种多范式语言,使用它的特性来发挥全部作用并没有错。几乎所有现实世界的 Common Lisp 代码都使用可变对象、数组甚至全局变量。 AFAIK Scheme 程序员尽可能地避免使用命令式代码。
标签: algorithm clojure lisp dynamic-programming knapsack-problem