该题为01背包的延伸,需要添加一个记录数组:
def ZeroOneBagCount(N, V, v, w):
memo = [0 for i in range(V+1)] ## 备忘录数组
count = [1 for i in range(V+1)] ## 增加一个计数数组(每种容量都至少有一种方案)
mod = 10**9+7
for i in range(N):
for j in range(V,v[i]-1,-1): ## 从最大容量开始向前循环到当前物品需要的最小容量(比v[i]小的容量再循环下去也没有意义)
if(memo[j] == memo[j-v[i]]+w[i]):
count[j] += count[j-v[i]] ## 若两者相等,则方案数为当前位置数加上剩余背包容量的方案数
elif(memo[j] < memo[j-v[i]]+w[i]):
count[j] = count[j-v[i]] ## 若不相等,则方案数和上一层方案数相等
memo[j] = max(memo[j], memo[j-v[i]]+w[i]) ## 更新备忘录数组中当前容量的最大价值
print(count)
print(count[-1]%mod)
N, V = map(int,input().split())
v, w = [], [] ## v为容量数组,w为价值数组
for i in range(N):
a, b = map(int, input().split())
v.append(a); w.append(b)
ZeroOneBagCount(N, V, v, w)
值得注意的是{ count[ j ] += count[ j - v [ i ]] } 和 { count[ j ] = count[ j - v [ i ]] } ,因为当前count[ j ] 与上一个物品的在不同背包容量的方案数有关,所以这么写,一定要注意!!!(j 是从最大到小循环,所以在 j 位置之前的count和memo都还是没更新上一个物品的记录)。