dp 0-1背包问题 python

这个是新学的动态规划问题中,经典的0-1背包问题。最主要的问题是清楚状态转移方程的使用方法,以及在索引时初始化的问题。(0-1背包,每个物体只能选一次,能多次选的是完全背包)

c = 10          #背包容量
w = [3,4,5,7]   #物体体积
v = [1,5,6,9]   #物体的价值
n = len(w)
dp = [[0 for i in range(c+1)]for j in range(1+n)]  #创建一个n*c的零矩阵
w.insert(0,0)  #因为dp表上次和左侧各有一列0,为了索引对齐
v.insert(0,0)  #在0位置加个0,相当于在v的0位置加个0 ,即1前加0
for i in range(1,n+1):
    for j in range(1,c+1):
        if w[i] <= j:       #物体体积小于背包体积时,有两种情况:
#要么是前一个装完最大,要么是装完现在这个还可以装其他的。
            dp[i][j] = max (dp[i-1][j],dp[i-1][j-w[i]] + v[i])
        else:
            dp[i][j] = dp[i-1][j]
print("最大价值为",dp[n][c])

接下来是0-1背包问题从二维压缩到一维,其实是因为我们从后往前计算可行,我们只用到前一行的数,并不会改变我们改行前面的数,因此我们可以进行迭代,达到节约空间的效果。

c = 10          #背包容量
w = [3,4,5,7]   #物体体积
v = [1,5,6,9]   #物体的价值
n = len(w)
dp = [0 for i in range(c+1)]
w.insert(0,0)  #因为dp表上次和左侧各有一列0,为了索引对齐
v.insert(0,0)  #在0位置加个0,相当于在v的0位置加个0 ,即1前加0
print(dp)
for i in range(1,n+1):
    for j in range(c,0,-1):  #从后往前算
        if w[i] <= j:       #物体体积小于背包体积时
            dp[j] = max (dp[j],dp[j-w[i]] + v[i])
        print(w[i],j)#逐次输入,方便观看每次的结果
        print(dp)

print("最大价值为",dp[c])

那我们实现完了这个问题之后,我们知道,因为只知道其价值,而不知道怎么拿物品是没有用的,所以我们现在就基于在知道物品价值的前提之下,来给出挑选物品的选择最优。

c = 10                      #背包容量
w = [3,4,5,7]               #物体体积
v = [1,5,6,9]               #物体的价值
n = len(w)
dp = [[0 for i in range(c+1)]for j in range(1+n)]  #创建一个n*c的零矩阵
w.insert(0,0)               #因为dp表上次和左侧各有一列0,为了索引对齐
v.insert(0,0)               #在0位置加个0,相当于在v的0位置加个0 ,即1前加0
for i in range(1,n+1):
    for j in range(1,c+1):
        if w[i] <= j:       #物体体积小于背包体积时,有两种情况:
#要么是前一个装完最大,要么是装完现在这个还可以装其他的。
            dp[i][j] = max (dp[i-1][j],dp[i-1][j-w[i]] + v[i])
        else:
            dp[i][j] = dp[i-1][j]
print("最大价值为",dp[n][c])

def get_path(dp,w,c):
    i = len(w)-1            #选中的物体
    j = c                   #背包的容量
    res = []
    while i != 0 and j != 0:  #上面的dp表0行和0列都等于0,所以我们只要索引到它即可
        if dp[i][j] == dp[i-1][j]:
            i -= 1
        else:
            res.append(i-1) #上边w,v都加了0,索引的时候减一,不然会出现0,会误导结果
            j -= w[i]       #背包面积减去装的物体,得到那时的背包体积
            i -= 1
    res.sort()
    return res
print("背包物品索引为",get_path(dp,w,c))
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值