动态规划之背包问题(算法图解书中例子实现)

**

动态规划之背包问题(算法图解书中例子实现)

**

背景

这里借用算法图解一书中的例子。

“假设一个小偷,背着一个可装4磅东西的背包。现在商场有三件物品分别为:
价值3000美元重4磅的音响,价值2000美元重3磅的笔记本,价值1500美元重1磅的吉他。问小偷应该怎样选择商品,才能使得偷取的价值最高?”

动态规划

动态规划的思路:
	 将待解决的问题划分为一个个小问题,动态规划先着手解决小问题,再逐步结局大问题。

就上面的问题来讲,动态规划的步骤为:
1.将背包分割为1磅,2磅,3磅,4磅在这几种情况下可偷取的最大价值为多少。
2.为了描述步骤1,可采用网格的形式来表述。网格的列为不同背包容量,行为可选择的商品。
在这里插入图片描述
3.然后按行向网格中填值。选择是下一行可以使用该行和其前面行的商品。
例如 音响行中只能偷取音响;笔记本行可以选择偷取笔记本和音响等。
网格填写的原则:在能放进该网格的前提下,使得网格的价值最大。
下图引用自博客:https://blog.csdn.net/superzzx0920/article/details/72178544
动态规划之背包问题(算法图解书中例子实现)_第1张图片
在这里插入图片描述
4.通过上述网格可知小偷偷取的最大价值为3500.

Python代码实现

这里说明一下在最大价值下打印要选择商品的思路:
1.通过bag()函数可以生成网格,即可定位出最大价值单元格。
2.最大价值单元格中所选商品一定包括该网格所在行的商品。
3.用最大价值-该行商品价值得到剩余价值,然后遍历网格,挑选出第一次出现剩余价值的单元格,则剩余价值中所选商品一定包括所在行商品。
4迭代步骤3,直至剩余价值==0.

#第一步建立网格(横坐标表示[0,c]整数背包承重):(n+1)*(c+1)
def bag(n,c,w,p):
    res=[[0 for j in range(c+1)]for i in range(n+1)]
    for j in range(c+1):
        #第0行全部赋值为0,物品编号从1开始.为了下面赋值方便
        res[0][j]=0
    for i in range(1 , n+1):
        for j in range(1 ,c+1):
           # print(res[i-1][j])
            res[i][j]=res[i-1][j]
            #生成了n*c有效矩阵,以下公式w[i-1],p[i-1]代表从第一个元素w[0],p[0]开始取。
            if(j>=w[i-1]) and res[i-1][j-w[i-1]]+p[i-1]>res[i][j]:
                res[i][j]=res[i-1][j-w[i-1]]+p[i-1]
              #  print("i=%d;j=%d;p[i-1]=%d;res[i][j]=%d" %(i,j,p[i-1],res[i][j]))
    return res
#打印最大价值和要选择的商品
def show(n,c,w,res):
    print('最大价值为:',res[n][c])
    rr= res[n][c] - p[n - 1]
    print ("第%d个" %(n-1))
    flag = False
    while rr !=0:
        for i in range(1,n+1):
            for j in range(1,n+1):
                if res[i][j] == rr:
                    print("第%d个" %(i-1))
                    rr = res[i][j] -p[i-1]
                    flag = True
            if flag:
                flag = False
                break


if __name__=='__main__':
    #物品件数
    n=3
    #背包的最大承重
    c=4
    #各个物品的重量
    w=[4,3,1]
    #各个物品的价值
    p=[3000,2000,1500]
    res=bag(n,c,w,p)
    show(n,c,w,res)

结果:
动态规划之背包问题(算法图解书中例子实现)_第2张图片

你可能感兴趣的:(算法图解)