[ 0/1 ] Knapsack Problem

Knapsack problem 將一群物品儘量塞進背包裡面,令背包裡面的物品總價值最高。背包沒有容量限制,無論物品是什麼形狀大小,都能塞進背包; 但是背包有重量限制,如果物品太重,就會撐破背包

「 0/1 」 每種物品只會放進背包零個或一個。一個物品要嘛整個不放進背包、要嘛整個放進背包。物品無法切割。

題目 :

水果 重量 價值
Apple 4 4500
Orange 5 5700
Banana 2 2250
Lemon 1 1100
Grape 6 6700

以上, 如果於背包總重量 8 時, 裝進的水果組合為最高價值是多少 ?

思路 : (可參考 https://liuhongyi1.gitbooks.io/algorithm/content/DP_TotalInclude.html)

//// k -> 目前背包剩餘重量
//// 條件 :
// 發生如果 arr[n].weight > k (表示沒選中, 此輪價值為 0)
if k > 0 && arr[n].weight > k :
    sub(arr[0~n], k) = sub(arr[0 ~(n-1)], k) + 0
// 正常情況 (比較 選目前的水果 和 下一個水果誰的價值大)
if k > 0:
    sub(arr[0~n], k) = or(sub(arr[0 ~ (n-1)], k - arr[n].weight) + arr[n].value, sub(arr[0 ~ (n-1)], k) + 0)

//// 終止 :
// 正常情況 (背包已經沒有重量)
if k == 0:
    return 0
// 剛好計算到只剩一筆 (看目前水果的重量是否等於 k, 如果是 return arr[0].value 回去否則 return 0)
if len(arr) == 1 && arr[0].weight == k :
    return arr[0].value
else :
    return 0

code (golang) common

package main

import (
    "fmt"
)

type Item struct{
    Item string
    Weight int
    Value int
}

var gWorkArray []*Item

func prepare(){
    gWorkArray = make([]*Item, 5)
    gWorkArray[0] = &Item{Item: "Apple", Weight:4, Value:4500}
    gWorkArray[1] = &Item{Item: "Orange", Weight:5, Value:5700}
    gWorkArray[2] = &Item{Item: "Banana", Weight:2, Value:2250}
    gWorkArray[3] = &Item{Item: "Lemon", Weight:1, Value:1100}
    gWorkArray[4] = &Item{Item: "Grape", Weight:6, Value:6700}
}

func max(a1 *int, a2 *int) int{
    if *a1 >= *a2{
        return *a1
    }
    return *a2
}

code (golang) 遞迴 (result : 9050)

func recursive(array []*Item, sum int) int{
    totalCount := len(array)
    if sum == 0{
        return 0
    }

    if totalCount == 1{
        if array[0].Weight == sum{
            return array[0].Value
        }else{
            return 0
        }
    }

    lastIndex := totalCount - 1

    if array[lastIndex].Weight > sum{
        return recursive(array[0: totalCount - 1], sum) + 0
    }

    selectionValue := recursive(array[0: totalCount - 1], sum - array[lastIndex].Weight) + array[lastIndex].Value
    noSelectionValue := recursive(array[0: totalCount - 1], sum) + 0
    return max(&selectionValue, &noSelectionValue)
}

func main(){
    prepare()
    fmt.Println("Recursive total weight 8 max value ->", recursive(gWorkArray, 8))
}

code (golang) 動態規劃 (result : 9050)

func getDpArray(totalSum int)[][]int{
    // dpArray[item][w]
    dpArray := make([][]int, len(gWorkArray))
    for i:= 0; i < len(gWorkArray); i++{
        dpArray[i] = make([]int, totalSum + 1)
        for j:= 0; j < (totalSum + 1); j++{
            dpArray[i][j] = 0
        }
    }
    return dpArray
}

func dp(sum int) int{
    dpArray := getDpArray(sum)
    // if w = 0
    for i:= 0; i < len(gWorkArray); i++{
        dpArray[i][0] = 0
    }
    // len(0)
    if gWorkArray[0].Weight <= sum{
        dpArray[0][gWorkArray[0].Weight] = gWorkArray[0].Value
    }
    // -- start arr[1][1] .. arr[1][2] ... end
    for itemIndex := 1; itemIndex < len(gWorkArray); itemIndex++{
        for sumIndex := 1; sumIndex < (sum + 1); sumIndex++{
            if gWorkArray[itemIndex].Weight > sumIndex{
                dpArray[itemIndex][sumIndex] = dpArray[itemIndex - 1][sumIndex] + 0
            }else{
                selection := dpArray[itemIndex - 1][sumIndex - gWorkArray[itemIndex].Weight] + gWorkArray[itemIndex].Value
                noSelection := dpArray[itemIndex - 1][sumIndex] + 0
                dpArray[itemIndex][sumIndex] = max(&selection, &noSelection)
            }
        }
    }
    return dpArray[len(gWorkArray)-1][sum]
}

func main(){
    prepare()
    fmt.Println("Dp total weight 8 max value ->", dp(8))
}

results matching ""

    No results matching ""