01 背包

\(01\) 的意图很明显,就是每个物品有 \(01\),即 不选 两种方式。

暴力

考虑设定一个状态 \(dp[i][j]\) 表示在前 \(i\) 个当中,花费为 \(j\) 所能获得的最大值。

转移可以:

优化

不难发现当前的 \(dp_{i,j}\) 只和 \(i-1\) 的部分有关系,于是滚动数组即可优化掉一维。

优化后的转移方程如下:

由于修改 \(dp_j\) 的时候需要 \(dp_{j-cost_i}\) 的值,所以需要先修改 \(dp_j\)\(j\) 较大的值。

时间复杂度 \(O(nT)\) 其中 \(T\) 是物品总数。

空间复杂度 \(O(m)\)\(m\) 是背包最大容量。


完全背包

完全 的意义在哪里呢?在于每一个物品可以被选取任意次,而并非 \(01\) 背包的 \(0/1\)

暴力

仍然是 \(dp_{i,j}\) 表示在前 \(i\) 个当中花费为 \(j\) 时所能得到的最大花费。

首先,考虑一个显然的做法,枚举每一个物品的出现次数:

优化

考虑如何去掉枚举 \(\max\) 的一维。

不难发现,只需要考虑 \(dp_{i,j}\)\(dp_{i-1,j-cost_i}+value_i\) 两部分即可。可为什么呢?

尝试使用数学归纳法来证明。

根据 \(01\) 背包的经验,可以很轻松的压掉一维。


多重背包

如何理解 多重 的意义呢?

意义比较容易理解,就是每一个物品只有有限个 \(num_i\)

暴力

首先,还是有一个很暴力的解法:

考虑将所有的物品看成 \(num_i\) 个物品,然后直接 \(01\) 背包。

时间复杂度是 \(O(m\displaystyle \sum_{i=1}^n num_i)\)

二进制优化

熟知,我们可以使用 \(k\) 位二进制来表示 \(1\)\(2^k\) 的所有数。

首先设 \(2^{\alpha_i+1}\le num_i < 2^{\alpha_i+2}\)

\(num_i\) 拆分成 \(\displaystyle\sum_{j=1}^{\alpha_i}2^i+(num_i-2^{\alpha_i+1}+1)\),这样就可以表示出 \(1\)\(num_i\) 之间的所有数。

之后再次用 \(01\) 背包就可以了。

时间复杂度为 \(O(m\displaystyle \sum_{i=1}^n \log_2num_i)\)


混合背包

何为混合?

就是将前面三种背包加起来。

非常简单。


二维费用背包

如果限制有两位呢,怎么求解?

设置状态 \(dp_{i,j,k}\) 表示在前 \(i\) 个物品中,限制 \(1\) 的花费为 \(j\),限制 \(2\) 的花费为 \(k\) 时所能得到的最大价值。

由于此时是三维的,所以需要使用 \(01\) 背包的方法再次优化掉第一维。

然后,枚举 \(i,j,k\) 即可。

时间复杂度 \(O(nT_{限制1}T_{限制2})\)


分组背包

考虑先枚举组数,然后再每一组中做 \(01\) 背包。

时间复杂度 \(O(nm)\) 其中 \(n\)\(k\) 组的物品的总种类。


有依赖的背包

有两种方法:

05-24 18:46