背包问题 动态规划_背包问题——动态规划

01 问题描述

fa1b2d55347ab307ca99a86552aa4618.png

    有n个物品,它们有各自的重量和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和?

02 问题分析

    1) 用V[i]表示物品的价值,w[i]表示物品的重量。定义状态dp[i][j]以j为容量放入前i个物品得到的最大价值。

    2) 初始化边界条件,V(0,j)=V (i,0)=0。

    3) 对于每个物品,有两种选择方法,装或者不装。

  • 第一,包的容量比该商品体积小,装不下,此时的价值与前i-1个的价值是一样的,即V(i,j)=V(i-1,j);

  • 第二,还有足够的容量可以装该商品,但装了也不一定达到当前最优价值,所以在装与不装之间选择最优的一个,即V(i,j)=max{V(i-1,j),V(i-1,j-w(i))+V(i)}其中V(i-1,j)表示不装,V(i-1,j-w(i))+v(i) 表示装了第i个商品,背包容量减少w(i)但价值增加了v(i);

    4) 得出递推关系式

a264ce7869a798ba4d5cc6430cbc6862.png

03 DP图解

    为了便于理解,设定如下参数:重量限制为8,能装4个物品。

2c381766b0e574d45d2c8384d47b1f01.png

    1) 初始状态将边界初始化为0。j表示背包的的重量,i表示第i个物品,填表方式为一行一行的填,每次填写的时候取 V(i-1,j)和V(i-1,j-w(i))+V(i)中的较大值。

227e93752b5e56b56f7a515c962c7d86.png

    2) 按照一行一行,从左至右进行填表。随便取一个举例子,比如第三行第五个的7,它是由v(2-1,5)=3和v(2-1)(5-3)+v(2) =7中的较大值比较出来的。即表示为容量为5时,可以不装第二个物品即为3或者装下第二个物品即为7。

497ca6456ab6c236236881373b8fa256.png

    3) 将数组更新完则是这样的情况。即得到在容量限制为8时,能装下的最大价值为10。

9da20fdedbede2134275c6fdee971272.png

04 算法设计

9297420f20201892333c4141c7683efe.png

05 空间优化

由上面的图解可以看出来,每一次改变的值只与V(i-1)(x)有关,V(i-1)(x)是前一次i循环保存下来的值(其中x(1,j))。因此,可以将二维数组V缩减成一维数组,从而达到优化空间的目的,状态转移方程转换为:dp(j)=max{dp(j),dp(j-w(i))+v(i)}

    并且,状态转移方程,每一次推导V(i)(j)是通过V(i-1)(j-w(i))来推导的,所以一维数组中j的扫描顺序应该从大到小(最大重量到0),否则前一次循环保存下来的值将会被修改,从而造成错误。

06 优化算法

4ed8c8b2d5a00db4db770029e5c80243.png

07 作者感悟

动态规划的实质就是把大问题拆成许多个小问题,通过寻找大问题和小问题之间的递推关系,解决每个小问题,最终达到解决原问题的结果。动态规划可以描述成通过填写表把所有已经解决的子问题答案记录下来,在新问题里需要用到的子问题可以直接提取,避免了重复计算,从而节约了时间,所以在问题满足最优性原理之后,用动态规划解决问题的核心就在于填表,表填写完毕,最优解也就找到。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值