一、问题描述
完全背包问题是一个经典的动态规划问题。其问题描述如下:
二、算法思路
- 定义状态
- 我们使用动态规划来解决这个问题。定义一个一维数组dp,其中dp[j]表示背包容量为 j时能获得的最大价值。
- 状态转移方程
- 对于每种物品i ,我们有两种选择:放或者不放。由于每种物品有无限件可用,我们可以从背包容量vi开始,一直到背包总容量V,更新dp数组。
- 状态转移方程为:
- 这里的含义是:对于背包容量为 j的情况,我们考虑放入第 i种物品。 dp[j-vi]表示在放入第i种物品之前背包容量为 j-vi时的最大价值,加上第i种物品的价值wi ,与不放入第 i种物品时的 dp[j]比较,取较大值。
- 初始化
- 初始化 dp数组为 0,表示背包容量为 0 时,最大价值为 0。
三、代码解析
以下是使用 C++ 实现完全背包问题的代码:
#include <iostream>
#include <vector>
using namespace std;
int main() {
int N, V;
cin >> N >> V;
// 定义向量v和w分别存储每种物品的体积和价值
vector<int> v(N);
vector<int> w(N);
// 定义dp数组,dp[j]表示背包容量为j时的最大价值
vector<int> dp(V + 1, 0);
// 输入每种物品的体积和价值
for (int i = 0; i < N; i++) {
cin >> v[i] >> w[i];
}
// 完全背包的核心算法
for (int i = 0; i < N; i++) {
for (int j = v[i]; j <= V; j++) {
dp[j] = max(dp[j], dp[j - v[i]] + w[i]);
}
}
// 输出背包容量为V时的最大价值
cout << dp[V] << endl;
return 0;
}
- 变量定义
- 首先,我们定义了整数 N和 V,分别表示物品的种类数和背包的容量。
- 然后,我们定义了三个向量
v
、w
和dp
。v
和w
分别用于存储每种物品的体积和价值,dp
用于存储不同背包容量下的最大价值。
- 输入处理
- 通过循环,我们输入了每种物品的体积和价值,并存储到
v
和w
向量中。
- 通过循环,我们输入了每种物品的体积和价值,并存储到
- 动态规划计算
- 外层循环
for (int i = 0; i < N; i++)
遍历每种物品。 - 内层循环
for (int j = v[i]; j <= V; j++)
从当前物品的体积 开始,到背包总容量 ,根据状态转移方程更新dp
数组。
- 外层循环
- 输出结果
- 最后,我们输出背包容量为 时的最大价值,即
dp[V]
。
- 最后,我们输出背包容量为 时的最大价值,即
四、总结
完全背包问题是动态规划中的一个重要问题,通过合理地定义状态和状态转移方程,可以有效地解决此类问题。上述代码通过简洁的实现,展示了如何使用动态规划来求解完全背包问题。在实际应用中,完全背包问题的思想可以应用于资源分配、投资组合等多个领域,具有广泛的应用价值。