返回
完全背包问题:从0到1,带领你攻克动态规划中的经典之作!
后端
2023-11-27 11:51:48
算法思想与动态转移方程的设计
首先,我们来理解完全背包问题中的“完全”一词所代表的含义。它意味着我们可以无限制地重复利用物品,也就是说,我们可以多次使用同一个物品来装入物品,而不用担心它被用完。
知道了这个问题的特殊性,我们就可以开始着手设计动态转移方程了。我们不妨设dp[i]
表示在前i
件物品中选择若干件,且总价值不超过j
的方案数。
那么,当我们考虑第i
件物品时,有两种可能:
- 选择第
i
件物品:此时,方案数等于在前i-1
件物品中选择若干件,且总价值不超过j-w[i]
的方案数。 - 不选择第
i
件物品:此时,方案数等于在前i-1
件物品中选择若干件,且总价值不超过j
的方案数。
综上所述,我们可以得到完全背包问题的动态转移方程:
dp[i] = dp[i - 1] + dp[i - w[i]]
其中,w[i]
表示第i
件物品的重量。
数组空间的优化
在设计好动态转移方程后,我们就可以开始着手解决完全背包问题了。最直接的方法是使用二维数组来存储dp
值,但这种方法会占用大量的空间。为了优化空间,我们可以使用一维数组来存储dp
值。
具体来说,我们可以将dp[i]
的值存储在dp[i % n]
中,其中n
是物品总数。这样,我们就只需要一个长度为n
的数组来存储dp
值,从而优化了空间。
代码实现
int main() {
int n, m;
cin >> n >> m;
vector<int> w(n + 1), v(n + 1);
for (int i = 1; i <= n; i++) cin >> w[i] >> v[i];
vector<int> dp(m + 1, 0);
for (int i = 1; i <= n; i++) {
for (int j = m; j >= w[i]; j--) {
dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
}
}
cout << dp[m] << endl;
return 0;
}
结语
完全背包问题是动态规划中非常经典且基础的题目,也是面试考察频率相当高的一个算法考题。通过本文的讲解,希望你能对完全背包问题有更深入的理解。如果你能掌握完全背包问题的解题思路和步骤,那么你就能在算法面试中大展身手,赢得面试官的青睐。