主要代码如下(Python):主要是讨论方法
from pathlib import Path
import matplotlib.pyplot as plt
#前两行是为了设置列表所需要引入的头文件
plt.rcParams['font.sans-serif']=['SimSun']#设置字体是为了折线图上的中文字体能够正确显示
#0-1背包问题
N=3 #物品数量
C=6 #背包容量
w=[3,4,2] #各个物品的重量
v=[5,2,7] #各个物品的价值
y=[0] #原始数据集2
x=range(0,N*C+1) #设定x轴的位置(因为总共需要计算N*C+1次)
result=[[0 for j in range(C+1)] for i in range(0,N+1)]#初始化结果为N+1个元素每个元素为含有C+1元素的列表
#动态规划法解决的思想
for i in range(1,N+1):
for j in range(1,C+1):
if j<w[i-1]:#表示装不下
result[i][j]=result[i-1][j]
else:#可以装下
if result[i-1][j-w[i-1]]+v[i-1]>result[i-1][j]:#装这个物品
result[i][j]=result[i-1][j-w[i-1]]+v[i-1]
else:
result[i][j]=result[i-1][j]
y.append(result[i][j])
plt.plot(x,y,label="动态规划算法",color="blue",linestyle="--",marker="s",markersize=4)
plt.xlabel("迭代次数") #x轴的文本说明
plt.ylabel("总价值") #y轴的文本说明
xlabel=[0]
for x in range(1,N*C+1):
xlabel.append(x)
plt.xticks(xlabel) #设定x轴刻度显示为文本
plt.title("0-1背包问题的动态规划算法总价值曲线")
plt.grid(color="r",linestyle=":") #为网格格式
plt.legend() #负责加载图例显示出来
plt.savefig(Path(__file__).name[0:-3]+".pdf") #对图片进行保存
plt.show() #将加载完毕的图片显示出来
首先对于result[i][j]表示为当背包容量为j时,前i个物品所能装下的物品的最大价值,由于i的值为从0-N,而j的值为从0-C,故而for循环中i,j的取值范围分别为range(N+1)与range(C+1),注意result二维数组相当于N+1行C+1列的二维数组,进行初始化令其全部值均为0,首先对于result[i][0]与result[0][j]值一定为0二者分别表示当背包容量为0或者要装入的物品为0时的背包所能代表的最大值,这也是进行动态规划思想得基础(之前博客也有提及),其次对于动态规划思想中的迭代表达式中,对于result[i][j]的计算问题,当j(也即是当前背包的总容量)<w[i-1]即为要装入的第i个物品的重量,则该第i个物品一定装不下,因此此时result[i][j]=result[i-1][j];即当容量为j时,装前i-1个物品与装前i个物品的总价值是一样的,否则(即最大容量能够装入第i个物品),比较result[i-1][j-w[i-1]]+v[i-1]与result[i-1][j]的值即比较(1假定首先已经装入第i个物品即价值加上v[i-1]而取剩下容量装前i-1个物品的最大价值即为result[i-1][j-w[i-1]]此时即为当装入第i个物品所能得到的最大价值)与(2假定一定不加入第i个物品所能取到的最大价值)的大小,谁更大则令result[i][j]取谁的值,至此当循环结束完毕二维数组result[i][j]也就构造完成,至于代码中的其他代码是为了构造出对应的求取次数与对应的总价值的折线图的代码,其中x轴为从0开始间隔为1且最大值为N*C的列表,表示进行了N*C次(即为求result[i][j]的次数)的求最大价值的计算,而对应的y则为求出来的对应的result[i][j]的值.至于其它的代码对于图层显示的方面注释已经十分详细,而其他的代码都是固定模式,进行套取接口。
最终折线图结果如下
至此动态规划解决0-1背包问题的代码讲解完毕。