完全背包

完全背包

问题描述:

N件物品和一个最多能背重量为V的背包。第i件物品的重量是weight[i],得到的价值是value[i]。每件物品都有无限个(也就是可以放入背包多次)。问如何选取物品放入背包,使得背包内的物品总价值最大?

决策方式:

(1)不放第i件物品

(2)放k件第i件物品,k>=1

状态转移方程:

\[ \begin{equation} dp[i][v] = \max\left\{ \max_{1 \leq k \leq \frac{v}{w[i]}} \left(dp[i-1][v-kw[i]] + kc[i]\right), dp[i-1][v] \right\} \end{equation} \]

其中dp[i][v]表示,容量为v时取前i个物品时背包能装入的最大值

化简

由于在第二种决策方式下,至少放一件 \[ \begin{equation} dp[i][v] = \max_{0 \leq k \leq \frac{v}{w[i]}-1} \left(\max\{dp[i-1][v-w[i]-kw[i]] + kc[i] + c[i], dp[i-1][v]\}\right) \end{equation} \] 对于状态转移方程可简化为: \[ \begin{equation} dp[i][v] = \max_{0 \leq k \leq \frac{v}{w[i]}} \left(dp[i-1][v-kw[i]] + kc[i]\right) \end{equation} \]v=v-w[i]时: \[ \begin{equation} dp[i][v-w[i]] = \max_{0 \leq k \leq \frac{v}{w[i]}-1} \left(dp[i-1][v-w[i]-kw[i]] + kc[i]\right) \end{equation} \] 整体替换到第二个公式中: \[ \begin{equation} dp[i][v] = \max\{dp[i][v-w[i]] + c[i], dp[i-1][v]\} \end{equation} \]

对比

01-背包状态转移方程: \[ \begin{align} dp[i][v] &= \begin{cases} \max\{dp[i-1][v-w[i]]+c[i], dp[i-1][v]\}, & \text{if } v - w[i] \geq 0 \\ dp[i-1][v], & \text{otherwise} \end{cases} \end{align} \] 完全背包状态转移方程: \[ \begin{equation} dp[i][v] = \begin{cases} \max\{dp[i][v-w[i]] + c[i], dp[i-1][v]\}, & \text{if } v - w[i] \geq 0 \\ dp[i-1][v], & \text{otherwise} \end{cases} \end{equation} \]

不难发现,完全背包状态转移方程仅仅比0-1背包状态转移方程少了一个-1

tips:0-1背包状态是回退到上一行,完全背包的状态仍然是当前行

一维滚动DP数组

图待更新

完全背包问题要沿着v的正方向进行枚举,这样才能为接下来的状态提供信息,否则当你需要计算dp[i][v]的时候,前面的dp[v-w[i]]还没有被更新过(同0-1背包问题完全一致,除了v的枚举方向)。

而0-1背包则需要逆向枚举v,防止要用到的上一行信息(dp[i-1][v-w[i]])被覆盖为当前行(dp[i][v-w[i]]


完全背包
http://showfaker.top/2024/03/09/完全背包/
作者
ShowFaker
发布于
2024年3月9日
许可协议