★代码实现(python):
#-*- coding:utf-8 -*-
from copy import copy
def add(p,x,c): #对应元素分别相加,p中每个元素都是元组,x也是一个元组
resultlist=[(i[0]+x[0],i[1]+x[1]) for i in p if i[0]+x[0]<=c]
return resultlist
def union(p,q): #求并集,同时删除坏点
pp=copy(p)
qq=copy(q)
delelement=[]
for i in pp:
for j in qq:
if(i[0]>=j[0] and i[1]<=j[1]):
delelement.append(i)
break
if(i[0]<=j[0] and i[1]>=j[1]):
delelement.append(j)
break
for i in delelement:
if i in pp:
pp.remove(i)
else:
qq.remove(i)
qq.extend(pp)
qq.sort()
return qq
def package2(w,v,c,n):#动态规划主函数
p=[[]]*(n+2)
p[n+1]=[(0,0)]
q= [[]] * (n + 2)
for i in range(n+1,1,-1):
q[i]=add(p[i],(w[i-2],v[i-2]),c)
p[i-1] = union(p[i], q[i])
return p,q
def out(w,v,p,q,n): #构造最优解
maxpoint=p[1][-1]
choose=[]
for i in range(1,n+1):
if((maxpoint in q[i+1]) and (maxpoint not in p[i+1])):
choose.append(True)
maxpoint=(maxpoint[0]-w[i-1],maxpoint[1]-v[i-1])
else:
choose.append(False)
print 'max weight and value:', p[1][-1]
print 'choose or not:', choose
if __name__=='__main__':
w=[2,2,6,5,4]
v=[6,3,5,4,6]
p,q=package2(w, v, 10, 5)
out(w,v,p,q,5)
★结果输出:
max weight and value: (8, 15)
choose or not: [True, True, False, False, True]
★复杂度分析
从之前的分析过程可以看出,每一个物品都存在选或者不选,如果没有删除坏点,
则要计算的转折点个数为2^n个,即指数级的,但是正是因为中间过程删除了很多
的坏点,因此实际复杂度并不是很高。
和前一篇最直接的动态规划相比,如果背包容量和物品重量的量级相差不大而
物品选择很多时,用直接动态规划方法效果可能更好。
而如果出现入本文开头引入的情况,即背包容量量级很大,而可选物品很少时,
用优化算法要快很多。因此,具体哪种好要视情况而定。
因为博客园编辑公式不太方便,因此写好了文档再截屏的。 以上内容为原创,希望能帮到大家。