想真正理解这道题,要先对动态规划法有一定的了解。
下面先介绍我能力范围内所能理解的动态规划法。
动态规划法
(1)阶段
(2)状态(子问题的解)
#通过对每一阶段,每一状态的目标值(即子问题)的求解与记录,最终求解问题时即借助子问题的最优值来求解最优值。
(3)状态转移方程(某种意义上的递推)
好了,下面开始做题
一个旅行者有一个承重最大为c公斤的背包,现在有n件物品,物品i的重量是wi,其价值为vi。
旅行者如何选择装入背包的物品, 使得装入背包中物品的总价值最大?
第一步 算法模拟
(0)杂七杂八
用xi表示物品是否放入背包,xi=0则表示未放入背包,xi=1则表示放入背包。
用vi表示i物品的价值。
用wi表示i物品的重量。
(1)阶段
用i表示阶段变量,i=1,2,3,……,n,表示n个物品
(2)状态
用j表示状态变量,表示背包还能装的物品的重量(0<=j<=C)
(3)状态转移方程(也就是一个递推关系公式)(关键部分)
Load[i][j]表示前i物品放入承重为j的背包所能得到的最大价值。用此递推公式分阶段一步步求解。
0 i = 0 or j = 0
Load[i][j] = Load[i-1][j] wi > j #此时背包放不下i物品,只能放前i-1个物品
max(Load[i-1][j] , Load[i-1][j-wi]+vi) wi<=j #此时背包可以放下i物品,但要求放与不放的最大值
(4)画个表,便于理解(行表示阶段,列表示状态)
第二步 编写代码
#(1)定义函数,即状态转移方程
def ZeroOneBag(w,v,c,x):
#函数的第一部分,求填完后的列表
Load = [[0 for j in range(c+1)] for i in range(len(w))]
for i in range(len(w)):
for j in range(c+1):
if i == 0 or j == 0:
Load[i][j] = 0
elif w[i] > j:
Load[i][j] = Load[i-1][j]
else:
Load[i][j] = max(Load[i-1][j],Load[i-1][j-w[i]]+v[i])
#函数第二部分,倒推回去,求最优解
j=c
for i in range(len(w)-1,0,-1):
if Load[i-1][j]==Load[i][j]:
x[i-1] = '未装'
else:
x[i-1] = '装'
j=j-w[i]
return Load[len(w)-1][c]
#(2)自定义原始数据,例如,背包的承重量为10kg(c=10),有5(n=5)件物品,其重量分别是{2, 2, 6, 5, 4},价值分别为{6, 3, 5, 4, 6}
w = [0,2,2,6,5,4]
v = [0,6,3,5,4,6]
c = 10
x = [0]*(len(w)-1)
#(3)输出结果
totalv = ZeroOneBag(w,v,c,x)
print('物品装入书包的状态:',x)
print('最大值为:',totalv)
输出结果: