【动态规划】01背包问题

01背包问题

在这里插入图片描述

点赞👍👍收藏🌟🌟关注💖💖
你的支持是对我最大的鼓励,我们一起努力吧!😃😃

1. 背包问题

背包问题 (Knapsack problem) 是⼀种组合优化的 NP完全问题

问题可以描述为:

你有一个背包,地上有一堆物品,挑选一些物品放入背包中。

问:最大能挑选出来的价值是多少?

如果就题目就这么简单,也太简单了,直接把所有物品都放背包里就行了。事情其实并没有这么简单。每个物品都有限定条件,比如说

  1. 物品的属性
  2. 背包的属性

物品编号从1开始,属性有价值、体积、还有个数,个数涉及背包问题的分类。
如果每个物品都有体积的话,那这个背包就有一个容量属性,假设是6。

在这里插入图片描述

所以说,不是把所有物品都放在背包里,而是只能挑选出一些放到背包里。

下面这几乎所有背包都是这样问的,你有一个背包有一个限制条件,然后把这些物品放到限制条件里,问最大能挑选出来的价值是多少?

在这里插入图片描述

然后根据 物品的个数,可以把背包分为若干类。

所有物品都只有一个,从这几个物品里面挑一些物品放到背包里,问最大能挑选出来价值是多少。这个问题我们称为01背包。为什么叫01背包,很简单,挑了某个物品这个物品就有一个,如果没挑,就只有0个。每个物品都面临选or不选两种情况,选了就是1,没选就是0。

在这里插入图片描述

所有物品都有∞个,可以在容量限制下,一直拿某个物品。问最大能挑选出来价值是多少。这个问题我们称为完全背包。
在这里插入图片描述
当然还有其他物品个数分类的情况:

  • 多重背包问题:每件物品最多有 si 个
  • 混合背包问题:每个物品会有上面三种情况…
  • 分组背包问题:物品有 n 组,每组物品里有若干个,每组里最多选⼀个物品

我们重点就研究01背包,完全背包问题。

其中上述分类里面,根据背包是否装满,又分为两类:

  1. 不必装满
  2. 必须装满

在这里插入图片描述
像这里就有四种组合了,比如01背包里面,它会问,不必装满最大价值是多少。必须装满最大价值是多少。

01背包问题是所有背包问题的基础!

2. 01背包

题目链接: DP41 【模板】01背包

题目分析:

在这里插入图片描述

第一问问的是背包不必要装满最大价值是多少。
第二问问的是背包必须装满最大价值是多少。

在这里插入图片描述

示例2,第二问,如果没有满足背包必须装满的情况,输出0

在这里插入图片描述

算法原理:

先解决第一问,背包不一定装满的情况:

1.状态表示

其实这个背包问题是一个线性dp问题,因为挑选物品的时候我们可以从左往右挑选。选或者不选这个物品。

线性dp,老套路了。继续根据 经验 + 题目要求

根据最后一个位置,结合题目要求,来定义一个状态表示。
如果是最后一个位置,相当于就是从编号1号物品挑到 i 号物品,也就是从前 i 个物品中挑选,要挑选出的最大价值。

dp[i] 表示:从前 i 个物品中选,所有选法中,能挑选出来的最大价值。

在这里插入图片描述

但是这个状态表示,推导不出来状态转移方程。推导 dp[i] 的时候可能要用到 i 之前的状态,也就是说求这个dp[i] 的时候会考虑这个 i 号物品选or不选,如果 i 号物品要选,那必须要保证背包要有容量能放下 i 号物品的体积。但是这个dp[i] 并不知道容量的信息。也就是说我要选 i 号物品的时候,根本就不知道背包此时的容量还有多少,我怎么能把 i 号物品放进去呢?因此上面一维状态表示推到不出来状态转移方程。

刚才状态表示没有体积这个条件,所以说,接下来我们把体积添加到状态表示:

dp[i][j] 表示:从前 i 个物品中选,总体积不超过 j,所有选法中,能挑选出来的最大价值。

在这里插入图片描述

2.状态转移方程

根据最后一步的状况,分情况讨论

从1号物品挑到 i 号物品,要么选择 i 号物品,要么不选 i 号物品。

不选 i 号物品,前面所有选法中,最后一个位置都不选 i 物品,是不是只去 1 ~ i - 1 号物品去挑,并且总体积依旧不等于 j,正好我们的状态表示就是从某个区间去挑,总体积不超过某个数,能跳的最大价值。

在这里插入图片描述

选 i 物品,所有选法中,最后一个位置一定选 i 物品,那肯定会有一个w[i]表示 i 号物品的价值,接下来去 1 ~ i - 1物品挑一个最大价值不就行了,但是此时的体积就不在是 j 了。因为挑到 i 号物品的时候总体积要求不超过 j ,那选了 i 号物品,然后从1 ~ i - 1物品选是不是要剩下一点体积能让我挑选 i 号物品啊,剩多少呢? j - v[i]。也就是说选了 i 号物品,接下来去1 ~ i - 1物品选总体积不超过j - v[i]最大价值,那正好在 dp[i-1][j-v[i]]里存着。

这里需要多考虑一点,j - v[i] 不一定存在。比如说挑选到 i 号物品的时候总体积要求不超过1,但是第 i 号物品的体积就已经等于5了。那怎么也装不下。那选 i 号物品这种情况就相当于不存在。如果想选 i 号物品这种情况存在,那 j - v[i]必须要有剩余空间。

在这里插入图片描述

然后我们取这两种情况的最大值就可以了

在这里插入图片描述

3.初始化

物品是从1开始的,也就是从数据下标1开始。相当于dp表天然多了一行多了一列

  1. 里面的值要保证后序的填表是正确的
  2. 下标的映射关系

在这里插入图片描述

第一行 i 等于0,表示从0号物品中选,但是我们没有0号物品,我们物品编号是从1开始的。i = 0相当于没有物品,如果没有物品,想凑成容量不超 j 根本不可能做到。

在这里插入图片描述

第一列表示 j 等于0,表示容量不超过0,但是物品总数有体积的,但是我不选不就可以了吗

在这里插入图片描述

4.填表顺序

填dp[i][j]依赖dp[i-1][…],也就是填 i 行 依赖于 i- 1行。所以从上往下填。

在这里插入图片描述

5.返回值

dp[i][j] 表示:从前 i 个物品中选,总体积不超过 j,所有选法中,能挑选出来的最大

评论 90
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值