Gup*_*pta 12 algorithm optimization knapsack-problem constraint-programming
假设有n个项目,例如i 1,i 2,...... i n,它们中的每一个都具有已知的有界权重w 1,w 2,... w n.还有一组m背包,例如k 1,k 2和k m.背包是同质的,它们都具有相同的容量W.功能F可以确定每个背包的得分.F的输入是每个背包中的项目.所以,
Score of each knapsack i = F(Items in knapsack i)
Run Code Online (Sandbox Code Playgroud)
现在我想把一些物品放在背包里,这样:
是否存在针对此问题的多项式时间解决方案?
注意:问题是0-1,即每个项目都可以选择.所有问题参数都是有界的.
编辑1:是不是可以减少这个问题来装箱,然后得出结论,这是一个NP难问题?
编辑2在此问题中,每个项目都有三个属性,例如属性a i,b i和c i.F函数是一个线性函数,它获取其中项目的属性并生成输出.
编辑3:本文似乎为多背包问题提出了一个精确的解决方案.可以用在我的情况下吗?
这个怎么样?
给定 Haskell 中 0-1 背包问题的标准动态解,可在此处找到,
inv = [("map",9,150), ("compass",13,35), ("water",153,200), ("sandwich",50,160),
("glucose",15,60), ("tin",68,45), ("banana",27,60), ("apple",39,40),
("cheese",23,30), ("beer",52,10), ("cream",11,70), ("camera",32,30),
("tshirt",24,15), ("trousers",48,10), ("umbrella",73,40),
("trousers",42,70), ("overclothes",43,75), ("notecase",22,80),
("sunglasses",7,20), ("towel",18,12), ("socks",4,50), ("book",30,10)]
knapsack = foldr addItem (repeat (0,[])) where
addItem (name,w,v) list = left ++ zipWith max right newlist where
newlist = map (\(val, names)->(val + v, name:names)) list
(left,right) = splitAt w list
main = print $ (knapsack inv) !! 400
Run Code Online (Sandbox Code Playgroud)
我们添加了一个填充机制,将库存排列顺序放置在下一个有空间的背包中,
stuff (name,w,v) left (v2,[]) = (v2,left)
stuff (name,w,v) left (v2,(cap, lst):xs) =
if w <= cap
then (v + v2, left ++ [(cap - w, (name,w,v):lst)] ++ xs)
else stuff (name,w,v) (left ++ [(cap,lst)]) (v2,xs)
Run Code Online (Sandbox Code Playgroud)
并将其替换为映射函数。把它们放在一起:
inv = [("map",9,150), ("compass",13,35), ("water",153,200), ("sandwich",50,160),
("glucose",15,60), ("tin",68,45), ("banana",27,60), ("apple",39,40),
("cheese",23,30), ("beer",52,10), ("cream",11,70), ("camera",32,30),
("tshirt",24,15), ("trousers",48,10), ("umbrella",73,40),
("trousers",42,70), ("overclothes",43,75), ("notecase",22,80),
("sunglasses",7,20), ("towel",18,12), ("socks",4,50), ("book",30,10)]
capacity = 200::Int
numKnapsacks = 3
stuff (name,w,v) left (v2,[]) = (v2,left)
stuff (name,w,v) left (v2,(cap, lst):xs) =
if w <= cap
then (v + v2, left ++ [(cap - w, (name,w,v):lst)] ++ xs)
else stuff (name,w,v) (left ++ [(cap,lst)]) (v2,xs)
knapsack = foldr addItem (repeat (0, replicate numKnapsacks (capacity,[])))
where addItem (name,w,v) list = left ++ zipWith max right newlist
where newlist = map (stuff (name,w,v) []) list
(left,right) = splitAt w list
main = print $ (knapsack inv) !! 600
Run Code Online (Sandbox Code Playgroud)
输出(总价值以及每个背包的剩余重量和内容):
*Main> main
(1062,[(1,[("map",9,150),("tshirt",24,15),("trousers",42,70),
("overclothes",43,75),("notecase",22,80),("sunglasses",7,20),
("towel",18,12),("socks",4,50),("book",30,10)]),
(0,[("compass",13,35),("cheese",23,30),("cream",11,70),
("camera",32,30),("trousers",48,10),("umbrella",73,40)]),
(1,[("sandwich",50,160),("glucose",15,60),("tin",68,45),("banana",27,60),
("apple",39,40)])])
Run Code Online (Sandbox Code Playgroud)