背包问题
有n件物品和容量为m的背包 给出i件物品的重量以及价值,
求解让装入背包的物品重量不超过背包容量且价值最大 。
一个讲解很好的博客。看了之后可以理解如何得到背包问题的状态转移方程。
1. 0/1背包问题
特点:每种物品只有一件,供你选择放与不放。
def Bag01(n, weights, values, cap):
dplist = [[0 for j in range(cap+1)] for i in range(n)]
for i in range(cap+1):
if weights[0] <= i:
dplist[0][i] = values[0]
for i in range(1, n):
for j in range(cap+1):
if weights[i] <= j:
dplist[i][j] = max(dplist[i-1][j], values[i] + dplist[i-1][j-weights[i]])
else:
dplist[i][j] = dplist[i-1][j]
return dplist[n-1][cap]
空间复杂度O(n*cap),可以观察出dplist的第i行只和第i-1行有关,所以可以简化为一维数组。
for i in range(1, n):
for j in range(cap, -1, -1):
if weights[i] <= j:
dplist[j] = max(dplist[j], values[i] + dplist[j-weights[i]])
2. 完全背包问题
特点:物品不再只有一个,可以无限复用。
def Bag3(n, weights, values, cap):
dplist = [[0 for i in range(cap+1)] for j in range(n)]
for i in range(1, cap+1):
num = i // weights[0]
dplist[0][i] = num*values[0]
for i in range(1, n):
for j in range(1, cap+1):
if weights[i] <= j:
num = j // weights[i]
dplist[i][j] = max(dplist[i-1][j], dplist[i-1][j-num*weights[i]] + values[i]*num)
else:
dplist[i][j] = dplist[i-1][j]
return dplist[n-1][cap]
一维数组
for i in range(1, n):
for j in range(cap, -1, -1):
if weights[i] <= j:
num = j // weights[i]
dplist[j] = max(dplist[j], dplist[j-num*weights[i]] + values[i]*num)
3. 多重背包问题
特点:物品不再可以无限复用,而是有数量限制。
def Bag4(n, weights, values, nums, cap):
dplist = [[0 for i in range(cap+1)] for j in range(n)]
for i in range(1, cap+1):
num = i // weights[0]
if num <= nums[0]:
dplist[0][i] = num*values[0]
else:
dplist[0][i] = nums[0]*values[0]
for i in range(1, n):
for j in range(1, cap+1):
if weight[i] <= j:
num = j // weights[0]
if num <= nums[0]:
dplist[i][j] = max(dplist[i - 1][j], dplist[i - 1][j - num * weights[i]] + values[i] * num)
else:
dplist[i][j] = max(dplist[i - 1][j], dplist[i - 1][j - nums[i] * weights[i]] + values[i] * nums[i])
else:
dplist[i][j] = dplist[i-1][j]
return dplist[n-1][cap]
一维数组
for i in range(1, n):
for j in range(cap, -1, -1):
if weight[i] <= j:
num = j // weights[0]
if num <= nums[0]:
dplist[j] = max(dplist[j], dplist[j - num * weights[i]] + values[i] * num)
else:
dplist[j] = max(dplist[j], dplist[j - nums[i] * weights[i]] + values[i] * nums[i])