Skip to content

Latest commit

 

History

History
94 lines (67 loc) · 3.48 KB

008背包问题.md

File metadata and controls

94 lines (67 loc) · 3.48 KB

如何解决背包问题

什么是背包问题

背包问题来源于生活,例如我们有一个容量有限的背包,现在有价格和重量不同的物品,如何组合才能让背包包含的物品总价格最大。如果每种物品只能选0次或1次,这样归纳为0-1背包问题。

为了简化,我们只考虑无界背包问题,也就是不限制物品的数量,如果要限制就是有界背包问题了。

背包问题算法设计

这也是一个动态规划问题,是否放置第i个物品,需要取决于背包中已经考虑的i-1时的所有情况,而与前面最大子数组和不同的是,这需要考虑i和容量二维变量。

我们假设物品数量是number,背包总容量是capacity,第i件物体价值(value)和重量(weight)分别是Vi、Wi,然后第i件物理的价值(result)是Ri。

唯一的算法就用数学表达就是R[i,w] = max{ R[i-1,w], R[i-i,w-Wi] + Vi },因此我们需要定义变量来记录每个i和每个剩余容量v时的值,这些子集结果可以复用因此适合动态规划的场景。

算法应该是这样,定义一个二维数组保存中间结果,for循环遍历物品i,for循环遍历剩余容量v,里面记录背包当时的最大价值。

如何编码解决背包问题

首先我们来定义这些题目的变量,物品数量是number,背包容量是capacity,重量的数组是weight_array,收益的数组是value_array。

number = 5
capacity = 10
weight_array=[2,2,6,5,4]
value_array=[6,3,5,4,6]

def zero_one_pack(n, c, w, v):
  # n is number
  # c is capacity
  # w is weight_array
  # v is value_array
  pass

zero_one_pack(number, capacity, weight_array, value_array)
# Print nothing

然后开始两个循环,首先循环i个物品,然后循环w的剩余空间,注意需要判断是否还有空间,如果没有空间只能和以前一样,如果有剩余空间就max一下。最后的result其实是一个二维数组,第一位是第i个物品,第二是剩余空间w,而值是那种情况下的背包最大价值。

number = 5
capacity = 10
weight_array=[2,2,6,5,4]
value_array=[6,3,5,4,6]

def zero_one_pack(n, c, w, v):
  # n is number
  # c is capacity
  # w is weight_array
  # v is value_array

  result=[[0 for j in range(c+1)] for i in range(n+1)]

  for i in range(1, n+1):
    for j in range(1, c+1):

      if j < w[i-1]:
        result[i][j] = result[i-1][j]
      else:
        result[i][j] = max(result[i-1][j], result[i-1][j-w[i-1]] + v[i-1])

  return result

zero_one_pack(number, capacity, weight_array, value_array)
# Print the matrix of max value 
'''
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 6, 6, 6, 6, 6, 6, 6, 6, 6],
 [0, 0, 6, 6, 9, 9, 9, 9, 9, 9, 9],
 [0, 0, 6, 6, 9, 9, 9, 9, 11, 11, 14],
 [0, 0, 6, 6, 9, 9, 9, 10, 11, 13, 14],
 [0, 0, 6, 6, 9, 9, 12, 12, 15, 15, 15]]
'''

最后还遗留一个问题,怎样才知道放了什么东西进去,这个必须是逆推的。其实可以通过判断,如果因为这个i导致与i-1的不同,也就是相同capacity下背包的最大值不同,也就是这个i-1被选中了。这里需要一个循环遍历所有item,从头开始或者从最后开始都可以。

  # Get the selected objects
  selection_array = [False for x in range(n)]
  capacity = c
  for i in range(1, n+1):
    if result[i][capacity] > result[i-1][capacity]:
      selection_array[i-1] = True
      capacity -= w[i-1]
      print(i-1)

这是本章内容,希望对你有所帮助。进入下一章