背包问题算法和原理
现有一个容量为Vol的背包,N个种类的物品,第i个物品的容量为weight[i],现在汪背包里面装东西,
怎么才能使背包物品的总价值才是最大的?主要分为三类:0-1背包,完全背包和多重背包问题
1,0-1背包问题
每件物品都可能被带走或者是留下,只能取0或1
def zero_one_Pack(Num,Vol,weight,value):
'''
0-1 背包问题(即每个物品只取一次或者不取)
:Param N 物品的个数 如 N=5
:Param V 背包的总容量,如 V=15
:Param weight 每个物品的重量数组 weight = [5,4,7,2,6]
:Param value 每个物品的机制数组表示,values = [12,3,10,3,6]
:return 返回最大的总价值
'''
# 初始化f[N+1][V+1]为0,f[i][j]对应前i个物品放入背包容量为j的最大价值
f = [[0 for col in range(Vol+1)] for row in range(Num+1)]
for i in range(1,Num+1):
for j in range(1,Vol+1):
if j < weight[i-1]: # 当容量小于商品i的重量时,直接不放入
f[i][j] = f[i-1][j]
else:
# weight,Value下标是从0开始,第i个商品的重量为Weight[i-1],价值为Value[i-1]
f[i][j] = max(f[i-1][j],f[i-1][j-weight[i-1]]+value[i-1]) # 状态方程
max_value=f[Num][Vol]
for _ in f:
print(_)
return max_value
if __name__ == "__main__":
N,V =5,15
weight = [5,4,7,2,6]
values = [12,3,10,3,6]
sol = zero_one_Pack(N,V,weight,values)
print(sol)
2,完全背包问题(部分背包问题)
物品可能被带走可以是无限次取,例如偷金沙
def complete_Pack(Num,Vol,weight,value):
'''
完全背包问题(每个物品可以无限次取)
Param: Num 物品的个数 如 N=5
Param: Vol 背包的总容量,如 V=15
Param: weight 每个物品的重量数组
Param: value 每个物品的机制数组表示
return: 返回最大的总价值
'''
# 初始化f[Num+1][Vol+1],为0
f = [[0 for col in range(Vol+1)] for row in range(Num+1)]
for i in range(Num+1):
for j in range(Vol+1):
f[i][j] = f[i-1][j]
for k in range(j//weight[i-1]+1):
if f[i][j] < f[i][j-k*weight[i-1]]+k*value[i-1]:
f[i][j] = f[i][j-k*weight[i-1]]+k*value[i-1]
max_value =f[Num][Vol]
for _ in f:
print(_)
return max_value
if __name__ == "__main__":
N,V =5,15
weight = [5,4,7,2,6]
values = [12,3,10,3,6]
sol = complete_Pack(N,V,weight,values)
print('结果为:',sol)
3,多重背包问题
物品被带走都是有限次,如第i个物品最多只能去num[i]次
def multi_Pack(Num,Vol,weight,value,num):
"""
多重背包问题(每个物品都有次数限制)
:Param Num 物品的个数 如 N=5
:Param Vol 背包的总容量,如 V=15
:Param weight 每个物品的重量数组
:Param value 每个物品的机制数组表示
:return 返回最大的总价值
:param num_out: 每个物品的个数限制,如num=[2,4,1,5,3]
"""
f = [[0 for col in range(Vol + 1)] for row in range(Num + 1)]
for i in range(Num+1):
for j in range(Vol+1):
min_num = min(j//weight[i-1],num[i-1])
f[i][j] = f[i-1][j]
for k in range(min_num+1):
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]
for _ in f:
print(_)
max_value = f[Num][Vol]
return max_value
if __name__ == "__main__":
N,V =5,15
weight = [5,4,7,2,6]
values = [12,3,10,3,6]
num=[2,4,1,5,3]
sol = multi_Pack(N,V,weight,values,num)
print('结果为:',sol)