0/1 计划中的背包

Posted

技术标签:

【中文标题】0/1 计划中的背包【英文标题】:0/1 Knapsack in Scheme 【发布时间】:2013-12-05 14:47:20 【问题描述】:

在计划中对背包问题进行编程是否走在正确的轨道上?我的程序不必考虑对象“值”,只考虑它们的权重。目标是选择最佳的物品组合,让我的包里有大约一半的重量。

(define (split-equip wlst)

 (define (sum lst)
  (define (sum-h accum lst1)
  (if (null? lst)
       (/ accum (length lst))
       (sum-h (+ (car lst1) accum) (cdr lst1))))
 (sum-h 0 lst))

(define (split-equip-h)
  (let ((target-w (/ (sum wlst) 2)))

我很想编写我的程序来输出一个包含所有可能的不同权重组合的列表,然后遍历该列表直到找到最佳的权重集,但不知道如何实现。

【问题讨论】:

你的想法是对的;计算所有组合,然后找到最接近(总重量)/2 的组合。可能有多个组合具有正确的权重,因此结果应该是一个组合列表。尝试先做组合部分。 【参考方案1】:

由于这已经是您第二次尝试(第一个问题已被删除),我将在 Racket 中向您展示一个解决方案。您应该像伪代码一样阅读它并将其翻译成您所学过的 Scheme 变体。

免责声明:我不擅长这类练习。这应该是您理解和重新表述这一点的另一个原因。但我的代码结果似乎仍然正确。

代码如下:

#lang racket

(define (knapsack lst)

  (define half (/ (apply + lst) 2))   ; compute half of total
  (printf "list  : ~a\nhalf  : ~a\n" lst half)

  (define (combs lst1 (lst2 null))    ; compute all the combinations  
    (if (null? lst1)
        (if (null? lst2) 
            null
            (list (reverse lst2)))
        (append
         (combs (cdr lst1) lst2)      ; case 1 -> we don't carry the iten
         (combs (cdr lst1) (cons (car lst1) lst2)))))   ; case 2 -> we do

  (for/fold ((delta half) (res null)) ((c (in-list (combs lst)))) ; determine the best fit
    (let* ((sm (apply + c)) (newdelta (abs (- half sm))))
      (cond
        ((< newdelta delta) (values newdelta (list c)))
        ((= newdelta delta) (values    delta (cons c res)))
        (else               (values    delta res))))))

(time 
 (let-values (((delta res) (knapsack (cdr (range 0 24 3)))))
   (printf "result: ~a\ndelta : ~a\n" res delta)))

这就是它所说的:

list  : (3 6 9 12 15 18 21)
half  : 42
result: ((3 6 12 21) (3 6 15 18) (3 9 12 18) (3 18 21) (6 9 12 15) (6 15 21) (9 12 21) (9 15 18))
delta : 0
cpu time: 6 real time: 5 gc time: 0

希望这会有所帮助。如果有什么你不明白的,不要犹豫,问问题!

【讨论】:

您介意解释答案的“for/fold”部分吗?如果它更接近目标重量,这件作品是否只是遍历您使用“combs”函数将 delta 设置为 newdelta 的列表? 是的。 delta 和 res 被初始化(一次),然后 c 被连续设置为来自梳子的每个组合。结果是(值 delta res)。

以上是关于0/1 计划中的背包的主要内容,如果未能解决你的问题,请参考以下文章

动态规划中的0-1背包问题怎么去理解?要求给出具体实例和详细步骤。。。

如何获取0-1背包中的选定物品列表?

C# 0-1 背包问题,已知集合中的总和和零个数

0-1背包问题

动态规划 0-1背包问题

0-1背包问题 —— 四种解法解题