完全背包
完全背包
问题描述:
有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]]
)