1、0-1背包
有一个容量为 j 的背包,要用这个背包装下物品的价值最大,这些物品有两个属性:体积 w 和价值 v。
一件物品有两种情况:装 or 不装;每个物品只能装一件;
对于物品 i,体积为 wi,价值为 vi:
(1)i 的体积 > 背包的体积,不装,此时背包的最大价值为不装 i 的价值 :
(1)i 的体积 < 背包的体积,可以装 也可以 不装,不装,同(1);装,则等同于将前 i-1 个物品装进剩余容量 j-w 的背包中,再加上物品 i 的价值,取两种可能的最大值,装了价值肯定最大:
def knapsack(W,N,weights,values):
dp = [[0 for i in range(W+1)] for j in range(N+1)]
for i in range(1,N+1):
w = weights[i-1]
v = values[i-1]
for j in range(W,0,-1):
if j >= w:
dp[i][j] = max(dp[i-1][j],dp[i-1][j-w]+v)
else:
dp[i][j] = dp[i-1][j]
print( dp[N][W]) # 11
W = 10
N = 3
weights = [3,4,5]
values = [4,5,6]
knapsack( W,N ,weights,values)
2、完全背包
'''完全背包'''
def CompletePack(N, V, weight, value):
"""
完全背包问题(每个物品可以取无限次)
:param N: 物品个数, 如 N=5
:param V: 背包总容量, 如V=15
:param weight: 每个物品的容量数组表示, 如weight=[5,4,7,2,6]
:param value: 每个物品的价值数组表示, 如value=[12,3,10,3,6]
:return: 返回最大的总价值
"""
# 初始化f[N+1][V+1]为0,f[i][j]表示前i件物品恰放入一个容量为j的背包可以获得的最大价值
f = [[0 for col in range(N + 1)] for row in range(V + 1)]
for i in range(1, V+1):
for j in range(1, N+1):
# 注意由于weight、value数组下标从0开始,第i个物品的容量为weight[i-1],价值为value[i-1]
# V/weight[i-1]表示物品i最多可以取多少次
f[i][j] = f[i - 1][j] # 初始取k=0为最大,下面的循环是把取了k个物品i能获得的最大价值赋值给f[i][j]
nCount = j//weight[i-1]+1
for k in range(nCount):
if f[i][j] < f[i-1][j-k*weight[i-1]]+k*value[i-1]:
f[i][j] = f[i-1][j-k*weight[i-1]]+k*value[i-1] # 状态方程
# 上面的f[i][j]也可以通过下面一行代码求得
# f[i][j] = max([f[i-1][j-k*weight[i-1]]+k*value[i-1] for k in range(j/weight[i-1]+1)])
max_value = f[V][N]
print(max_value)
return max_value
W = 10
N = 3
weights = [3,4,5]
values = [4,5,6]
CompletePack(W,N ,weights,values) #13