方案中的0/1背包

时间:2013-12-05 14:47:21

标签: recursion scheme knapsack-problem

我是否正在计划方案中的背包问题?我的程序不必考虑对象“值”,只考虑它们的权重。我们的目标是采用最好的物品组合,这样我的包里就有大约一半的重量。

(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)))

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

1 个答案:

答案 0 :(得分: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

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