📅  最后修改于: 2023-12-03 15:40:08.591000             🧑  作者: Mango
无界背包是背包问题的一个变种,即一个物品可以选择多次放入背包,与 0/1 背包、完全背包不同。在无界背包中,物品有一个重量和一个价值,背包有一个容量限制,要求选择物品的重量总和不超过背包的容量,每个物品可以选择无限次放入背包,使得放入背包的物品的价值总和最大。
无界背包可以通过动态规划来解决,而动态规划又可以通过状态转移方程来实现。
首先,我们定义一个一维数组 $dp$,其中 $dp[i]$ 表示容量为 $i$ 的背包所能达到的最大价值。
对于每个物品 $j$,可以选择无限次放入背包。所以,我们可以遍历所有小于等于背包容量的子问题,对于每个子问题都选择物品 $j$ 放入背包,然后再求解剩余容量下的最大价值。由于物品可以无限次选择,所以在选完物品 $j$ 后还可以继续选择物品 $j$ 。
状态转移方程如下:
$dp[i] = max(dp[i], dp[i-weight[j]]+value[j])$
其中,$weight[j]$ 表示物品 $j$ 的重量,$value[j]$ 表示物品 $j$ 的价值。这个方程的意义是:当选择物品 $j$ 放入背包时,当前容量为 $i$ 的背包所能达到的最大价值等于两种方案中的最大值,一种是不选择该物品直接使用 $dp[i]$,递推式为 $dp[i]$;另一种是选择该物品,此时背包的容量需要减去其对应的重量,即 $i-weight[j]$,而当前价值应该添加上该物品的价值 $value[j]$,递推式为 $dp[i-weight[j]]+value[j]$。
重复执行这个状态转移方程,直到子问题的容量大于当前背包的容量为止。最终,$dp[capacity]$ 就代表了在背包容量为 $capacity$ 的情况下所能达到的最大价值。
这是一个 Python 的无界背包解法的示例:
def unbounded_knapsack(capacity, weights, values):
dp = [0] * (capacity+1)
for i in range(1, capacity+1):
for j in range(len(weights)):
if weights[j] <= i:
dp[i] = max(dp[i], dp[i - weights[j]] + values[j])
return dp[capacity]
这是一个 C++ 的无界背包解法的示例:
int unboundedKnapsack(int capacity, vector<int>& weights, vector<int>& values) {
vector<int> dp(capacity+1);
for (int i = 1; i <= capacity; ++i) {
for (int j = 0; j < weights.size(); ++j) {
if (weights[j] <= i) {
dp[i] = max(dp[i], dp[i - weights[j]] + values[j]);
}
}
}
return dp[capacity];
}
以上的示例中,无界背包的容量为 capacity
,物品的重量和价值分别由 weights
和 values
表示。通过遍历所有子问题并应用状态转移方程,最终计算出了在背包容量为 capacity
的情况下所能达到的最大价值。