0-1背包问题
给定n个重量为w1, w2, w3,…, wn,价值为 v1, v2, v3,… vn的物品和容量为C的背包,物品选择取与不取,且只能取一次。求这个物品中一个最有价值的子集,使得在满足背包的容量的前提下,包内的总价值最大。
w=[2,2,6,5,4] #物品i的重量 i对应物品下标 [2,2,6,5,4]
v=[6,3,5,4,6] #物品i的价值 i对应物品下标 [6,3,5,4,6]
C=10 #背包容量为10
x=[0,0,0,0,0] #物品i装入背包的份额 0表示物品不装入背包 1表示完全装入背包
三种算法
1.贪心算法_单位最大价值优先
#将物品按单位价值从大到小排序 返回数组y:元素为排序后的物品下标
def Sort():
vi={}
for i in range(len(w)):
vi[i]=v[i]/w[i]
vi=sorted(vi.items(), key=lambda kv: (kv[1], kv[0]),reverse=True)
result=[]
for key,value in vi:
result.append(key)
return result
#贪心算法_最大单位价值优先
def Func_Greedy():
vi=Sort()
remain_c=C
value_sum=0
for i in vi:
if(w[vi[i]]<=remain_c):
x[vi[i]]=1
value_sum+=v[vi[i]]
remain_c-=w[vi[i]]
return value_sum
2.分治法
#分治法_递归
def Func_3(i,c):
if(i==-1 or c==0):
return 0
if(c<w[i]):
return Func_3(i-1,c)
else:
tmp1=Func_3(i-1,c)
tmp2=Func_3(i-1,c-w[i])+v[i]
return max(tmp1,tmp2)
3.动态规划
#动态规划
def Func_2():
m=[[0 for i in range(11)]for i in range(5)] #创建一个4*10的数组 列对应物品 行对应背包容量
for i in range(1,C+1):#背包装入第一件物品 初始化第一行
if(i>=w[0]):
m[0][i]=v[0]
for i in range(1,5):#第一行已初始化,从第二行开始
for j in range(1,11):#第一列意思是背包容量等于0, 从第二列开始
if(j<w[i]):
m[i][j]=m[i-1][j]
else:
if(m[i-1][j-w[i]]+v[i]>m[i-1][j]):
m[i][j]=m[i-1][j-w[i]]+v[i]
else:
m[i][j]=m[i-1][j]
return m[len(w)-1][C]