Algorithm Analysis (CSC 301 2015F) : EBoards

CSC301.01 2015F, Class 34: Dynamic Programming (2)


Overview

Preliminaries

Admin

Upcoming Work

Extra Credit

Academic

Peer

No Extra Credit, But Good

Questions

A DP Solution to the Stamps Problem

The Knapsack Problem

How do we modify that code to achieve a solution to the knapsack problem?

                Stamps                  Knapsack
                ------                  --------
Input 1         total price             total weight

Input 2         list of stamp costs     list of weight/value pairs

Output          list of stamps          list of weight/value pairs

Restrictions    (sum lst) = price       (sum weights) <= total weight
                Stamps can appear       Each pair can appear at most once
                  multiple times

Goal            Minimize (length lst)   Maximize (sum values)

Sample call

(knapsack 100 (list (vector "cat1" 8 1) (vector "cat2" 9 1)
                    (vector "kitten1" 2 1) (vector "kitten2" 2 1)
                    (vector "ukitten1" 1 1) (vector "ukitten2" 1 1)
                    (vector "dog" 35 100) (vector "lizard" 40 20)
                    (vector "mm" 120 300)))

Improve call

(knapsack 37 (list (vector "knife" 1 3) (vector "knife" 1 2)
                   (vector "knife" 1 2) (vector "knife" 1 1)
                   (vector "knife" 1 1) (vector "knife" 1 1)
                   (vector "flashlight" 2 5) (vector "flashlight" 2 3)
                   (vector "flashlight" 2 1) (vector "flashlight" 2 1)
                   (vector "blanket" 7 10) (vector "extra blanket" 7 5)
                   (vector "another blanket" 7 1)
                   (vector "tent" 15 20) (vector "spare tent" 15 6)
                   (vector "complete-kamping-kit" 25 25)))

What changes should we make to the algorithm as stated? (Either Scheme code or conceptially?)

(define knapsack
  (lambda (limit things)
    (let ([table (make-vector (+ limit 1) #f)])
      (vector-set! table 0 (cons 0 null))
      (let loop ([pos 1])
        (when (<= pos limit)
          (log)
          (log "Finding the optimal value for" pos)
          (let kernel ([guess (vector-ref table (- pos 1)] ; A starting point
                       [lst thing])
            (cond
              [(null? lst)
               (log "The optimal value for" pos "is" guess)
               (vector-set! table pos guess)
               (loop (+ pos 1))]
              [else
               (let* ([val (car lst)]
                      [remainder (- pos (weight val)])
                 (log "Trying item" (car lst))
                      " giving us a remainder of" remainder)
                 (cond
                   [(negative? remainder)
                    (log "  Negative remainder.  Item too heavy!")
                    (kernel guess (cdr lst))]
                   [else
                    (let ([alternate (vector-ref table remainder)])
                      (log "  Best option for" remainder "is" (cdr alternate) 
                           "which has value" (car alternate))
                      (cond
                        [(and (> (+ (worth val) (car alternate)) (car guess))
                              (...))
                         (let ([newguess (cons (+ 1 (car alternate))
                                               (cons val (cdr alternate)))])
                           (log "  Updating best guess to" (cdr newguess)
                                "which is" (car newguess) "stamps")
                           (kernel newguess (cdr lst)))]
                        [else
                         (log "  Retaining prior guess")
                         (kernel guess (cdr lst))]))]))]))))
        (let ([answer (vector-ref table value)])
           (if answer
               (cdr answer)
               (error "It is not possible to make a value of" value))))))

The String Matching Problem