动态规划(2)0/1背包

题目描述
小明有一个容量为 V的背包。
这天他去商场购物,商场一共有 N件物品,第 i件物品的体积为 wi,价值为 vi。
小明想知道在购买的物品总体积不超过 V的情况下所能获得的最大价值为多少,
请你帮他算算。
输入描述
输入第 1行包含两个正整数 N,V,表示商场物品的数量和小明的背包容量。
第2-N+1行包含2个正整数 w,v,表示物品的体积和价值。
1<=N<=10^2,1<=V<=10^3,1<=wi,vi<=10^3。
输出描述
输出一行整数表示小明所能获得的最大价值。
输入输出样例
示例 1
输入
5 20
1 6
2 5
3 8
5 15
3 3
输出
37
运行限制
最大运行时间:1s
最大运行内存: 128M

笔记:

DP状态设计:
    DP状态:定义二维数组dp[][],大小为N*C。
    dp[i][j]:将前i个物品(从第1个到第i个)装入容量为j的背包中获得的最大价值。
解题思路:
    把每个dp[i][j]看成一个背包:背包容量为j,装1-i这些物品。
    从dp[0][0]递推到dp[N][C]
    dp[N][C]是问题的答案:把N个物品装进容量为C大的背包的最大价值。
DP转移方程:
    (1)第i个物品的体积比容量j大,装不下去。
    直接继承i-1个物品装进容量j的背包的情况即可;
    dp[i][j]=dp[i-1][j]
    (2)第i个物品的体积比容量j小,可以装进背包。
    装第i个:第i个物品装进背包后,背包容量减少c[i],价值增加w[i]:
        dp[i][j]=dp[i-1][j-c[i]]+w[i]
    不装第i个:dp[i][j]=dp[i-1][j]
    取最大值,状态转移方程:
     dp[i][j]=max(dp[i-1][j],dp[i][j]=dp[i-1][j-c[i]]+w[i])
eg有四个物品,体积分别为{2,3,6,5},价值分别为{6,3,5,4},背包容量为9
dp[][]表:
包装容量:a \ b 0 1 2 3 4 5 6 7 8 9
   不装:0
装前一个:1
装前二个:2
装前三个:3
装前四个:4
->dp[a][b]
步骤一:只装第一个物品
c1=2, a \ b 0 1 2 3 4 5 6 7 8 9
w1=6  0     0 0 0 0 0 0 0 0 0 0
      1     0 0 6 6 6 6 6 6 6 6
    物品1的体积2,所以背包容量小于2的,放不进去,得dp[1][0]=dp[1][1]=0;
    物品1的体积等于背包容量,能装进去,背包价值等于物品1的价值,
        dp[1][2] = 6;
    容量大于2的背包,多余的容量用不到,所以价值容量2的背包一样
步骤2:只装前2个物品。
    如果物品2体积比背包容量大,那么不能装物品2,情况和只装第1个一样
        dp[2][0] = dp[2][1] = 0,dp[2][2] = 6。
    dp[2][3]?物品2体积等于背包容量,那么可以装物品2,也可以不装:
    (a) 如果装物品2(体积是3,价值也是3),那么可以变成一个更小的问题
    即只把物品1装到(容量j-3)的背包中。
    dp[2][3]=3+0(3(目前最大容量(j)-装入物品体积(3))=3
    (b) 如果不装物品2,那么相当于只把物品1装到背包中取(a)和(b)的最大值,
    得dp[2][3] = max3,6) = 6(直接继承)
    ∴ 不装更好一些
后续步骤: 继续以上过程,最后得到下图(图中的箭头是几个例子)最后的答案是
    dp[4][9]: 把4个物品装到容量为9的背包,最大价值是11。
   包装容量:a \ b 0 1 2 3 4 5 6 7 8 9
      不装:0     0 0 0 0 0 0 0 0 0 0
c1=2,w1=6:1     0 0 6 6 6 6 6 6 6 6
c2=3,w2=3:2     0 0 6 6 6 9 9 9 9 9
c3=6,w4=5:3     0 0 6 6 6 9 9 9 11 11
c4=5,w4=4:4     0 0 6 6 6 9 9 10 11 11
复杂度:n*c
N, V = map(int, input().split())
dp = [0]*(V+1)
for _ in range(N):
  w, v = map(int, input().split())
  for j in reversed(range(w,V+1)):
    dp[j] = max(dp[j], dp[j-w]+v)
print(dp[-1])

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值