我一直在玩一个众所周知的背包问题。这一次 - 然而 - 我决定在 F# 中实现它,因为我正在学习该语言并发现它特别有趣。
我已经设法实现了算法的主要部分,但我也需要回溯。不幸的是,我在网上找到的所有信息都使用了 Haskell,我还不知道(还;))。
作为占位符,我使用可变变量实现了回溯(无需详细说明,“组合 (i, k)”返回 i 项和 k 容量的部分解决方案):
let output =
List.rev
[
let i = ref N
let k = ref K
// analize items starting with the last one
for item in Array.rev items do
match !k - item.Size with
// if size of i-th item is greater than current capacity...
| x when x < 0 -> i := !i - 1
// ... this means we haven't taken this item
yield 0
// otherwise we've got two cases
| x when x >= 0 -> let v1 = combinations (!i-1, !k) id
let vc = combinations (!i, !k) id
if v1 = vc then
// case 1: item hasn't been taken
i := !i - 1
yield 0
else
// case 2: item is contained in the optimal solution
i := !i - 1
k := x
yield 1
]
List.iter (fun x -> printf "%A " x) output
我相信在 F# 中有更好的方法来做到这一点(例如使用计算表达式)。我很高兴听到有关如何以功能样式实现此功能的任何提示/信息。
最后一件事:请记住我是函数式编程的新手,并尽量避免像我发现的那样使用一些魔术表达式:
“单子是内函子类别中的一个幺半群,有什么问题?” :)