问题:4个物品,其重量分别为1,3,5,7,其价值分别为2,4,6,8 背包容量为10,0 1背包求解:
贪心:
import time
w=[1,3,5,7]
v=[2,4,6,8]
n=4
allw=10
begin=time.time()
s=sorted(list(zip(w,v)),reverse=True)
bestv=0
res=[0]*4
for i in range(4):
if s[i][0]<allw:
bestv+=s[i][1]
res[i]=1
allw-=s[i][0]
elif s[i][0]>=allw:
res[i]=0
print(bestv)
print(res)
end=time.time()
print(end-begin)
10
[1, 0, 0, 1]
0.03200888633728027
明显没有得出最优解
动规:
import time
w=[0,1,3,5,7]
v=[0,2,4,6,8]
allw=10
s=[0]*5
begin=time.time()
dp=[[0 for i in range(11)]for i in range(5)]
for i in range(5):
for j in range(11):
if j<w[i]:
dp[i][j]=dp[i-1][j]
else:
dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])
for i in range(5):
res=[]
for j in range(11):
res.append(dp[i][j])
print(res)
def back(i,j):
if i>0:
if dp[i][j]==dp[i-1][j]:
s[i]=0
back(i-1,j)
elif j-w[i]>=0 and dp[i][j]==dp[i-1][j-w[i]]+v[i]:
s[i]=1
back(i-1,j-w[i])
back(4,10)
print('------------------------------')
print(s)
end=time.time()
print(end-begin)
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
[0, 2, 2, 4, 6, 6, 6, 6, 6, 6, 6]
[0, 2, 2, 4, 6, 6, 8, 8, 10, 12, 12]
[0, 2, 2, 4, 6, 6, 8, 8, 10, 12, 12]
------------------------------
[0, 1, 1, 1, 0]
0.08184647560119629
此时的结果是12 明显比贪心好
回溯:
import time
bestV=0
curW=0
curV=0
bestx=None
begin=time.time()
def backtrack(i):
global bestV,curW,curV,x,bestx
if i>=n:
if bestV<curV:
bestV=curV
bestx=x[:]
else:
if curW+w[i]<=c:
x[i]=True
curW+=w[i]
curV+=v[i]
backtrack(i+1)
curW-=w[i]
curV-=v[i]
x[i]=False
backtrack(i+1)
if __name__=='__main__':
n=4
c=10
w=[1,3,5,7]
v=[2,4,6,8]
x=[False for i in range(n)]
backtrack(0)
print(bestV)
print(bestx)
end=time.time()
print(end-begin)
12
[True, True, True, False]
0.09200620651245117
分支限界:
import numpy as np
import queue
import math
import time
w = [1,3,5,7]#体积
v = [2,4,6,8]#价值
N=4
begin = time.time()
def test(capacity):
vec_len = 2**(len(v)+1) - 1#树的节点个数
vec_v = np.zeros(vec_len)
vec_w = np.zeros(vec_len)
vec_w[0]=capacity
que = queue.Queue();
que.put(0)
best = 0
while(not que.empty()):
current = que.get()
level = int(math.log(current+1,2))
if(vec_v[current] > vec_v[best]):
best = current
left = 2*current+1#左子树索引
right = 2*current+2#右子树索引
if(left < vec_len and vec_w[current]-w[level] >= 0 ):
vec_v[left] = int(vec_v[current]+v[level])
vec_w[left] = vec_w[current]-w[level]
que.put(left)
if(right < vec_len and sum(v[level+1:N])+vec_v[current] >= vec_v[best]):
vec_v[right] = vec_v[current]
vec_w[right] = vec_w[current]
que.put(right)
print(vec_v[best])
test(10)
end = time.time()
print(end-begin)
12.0
0.0665130615234375