背包9讲——完全背包问题及变种问题
作者:互联网
完全背包问题
经典题目
与01背包不同的是,我们可以将物体无限制放入,01背包是只允许放入一件件,其他条件同理,问在不超过背包体积的限制下,怎么使得背包内物体价值最大。
基本思路
当然我们可以用贪心算法,算出单位体积最大价值,再依次递减直到无法放入,但是如果我们用动态规划思路,同样我们需要给出状态转移方程。
同样我们定义一个二维数组,下标分别记为i和v,则F[i][v]表示在前i件物品中体积为v是的最大价值。那么我们要求的就是放入所有物体后的最大体积
假使我们到第i个物体时候,我们知道第前i-1个物体在不同v下的最大价值,也就是F[i-1][V]都知道;那么我们第i个物体就有很多种选择方式,假设有k种选择,那么k满足以以下条件
0
<
=
k
V
i
<
=
V
0<=kVi<=V
0<=kVi<=V
其中v是我们背包的最大体积;Ci是第i物体的体积;
那么我们取到第i个时候哦就只需要针对这k种选择方式取最大值,即:
F
[
i
]
[
v
]
=
m
a
x
F
[
i
−
1
]
[
V
−
K
V
i
]
+
k
W
i
∣
0
<
=
k
V
i
<
=
V
F[i][v]=max{F[i-1][V-KVi]+kWi|0<=kVi<=V}
F[i][v]=maxF[i−1][V−KVi]+kWi∣0<=kVi<=V
复杂度
时间复杂度
这个跟01背包问题一样有O(VN)个状态需要求解,每个的复杂度如果忽略可以表示为O(NV);
空间复杂度
跟01背包一样都是O(VN),但是其实可以优化
优化时间复杂度
有一个简单的优化方式,用一对值来记录已经考虑的空间和价值,如果后续发现有一个值的空间大于记录的空间值,并且它的价值小于记录的价值,那么我们直接i+1,就当这个物体不存在;
如果后续有一个物体的空间小于记录的值,价值大于记录的值,那么我们更新这一对值;
显然这种优化方式对最坏时间复杂度没有什么帮助,仅仅只是优化了最好和平均。
这里我们只考虑对动态规划的时间复杂优化,贪心算法不考虑
01背包转化
很简单,我们把第i个物品能够放进去的个数分别做成一个新的物体,拆成k个值,这样问题就转化为了01背包问题,但是这种方式完全没有改进时间复杂度,并且加大了空间复杂度,
值得注意的是:我们其实不需要每个k都写出来,因为我们知道只要按照二进制进行不断地乘2,那么这些数总能组成任意k个数的组合,因此这样可以优化一部分空间复杂度;
优化空间复杂度
同01背包问题,我们可以用一维数组来表示二维数组,一维数组的脚标表示不同的体积下对应最大价值;那我们同样可以用以下方法更新v;
F
[
v
]
=
m
a
x
(
F
[
v
]
,
F
[
v
−
V
i
]
+
W
i
)
F[v]=max(F[v],F[v-Vi]+Wi)
F[v]=max(F[v],F[v−Vi]+Wi)
问题是如何定义外围循环,我们先想想01背包是如何简化的,他是为了保证每次访问到的F[i]都是从F[i-1]递推而来的,所以从最大v递减,从而不会更新F的值,这种处理方式正是为了避免我们多次从数组中拿同一个对象;
而完全背包恰好相反,我们可以依赖更新后的值,因此我们只需要将对空间的遍历反过来就行了,也就是这样:
上面也就知道对v的遍历次序反过来了而已;
变种题目
https://leetcode-cn.com/problems/coin-change/
https://leetcode-cn.com/problems/coin-change-2/
上面的讲解比我讲得好,各位看看解析就可以了
标签:背包,变种,复杂度,问题,01,物体,优化,我们 来源: https://blog.csdn.net/weixin_42034081/article/details/118383763