python实现01背包 不同解法

问题: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

猜你喜欢

转载自blog.csdn.net/A52091/article/details/106272318