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]