📜  无界背包(允许重复物品)| 2套

📅  最后修改于: 2021-09-17 07:49:20             🧑  作者: Mango

给定一个整数W ,数组val[]wt[] ,其中val[i]wt[i]是第 i 个项目的值和权重,任务是计算使用权重不能获得的最大值超过W
注意:每个权重可以包含多次。

例子:

朴素的方法:参考上一篇文章,使用传统的无界背包算法解决问题。
时间复杂度: O(N * W)
辅助空间: O(W)

高效的方法:上述方法可以基于以下观察进行优化:

  • 假设第i索引为我们提供了给定数据中每单位重量的最大值,这很容易在O(n) 中找到
  • 对于任何大于或等于wt[i] 的权重 X ,最大可达值将是dp[X – wt[i]] + val[i]
  • 我们可以使用传统算法计算 dp[]0wt[i]的值,我们还可以计算我们可以适合 W 权重的i 个项目的实例数。
  • 所以所需的答案将是val[i] * (W/wt[i]) + dp[W%wt[i]]

下面是新算法的实现。

Python3
# Python Program to implement the above approach
  
from fractions import Fraction
  
# Function to implement optimized
# Unbounded Knapsack algorithm
def unboundedKnapsackBetter(W, val, wt):
  
    # Stores most dense item
    maxDenseIndex = 0
  
    # Find the item with highest unit value
    # (if two items have same unit value then choose the lighter item)
    for i in range(1, len(val)):
          
      if Fraction(val[i], wt[i]) \
            > Fraction(val[maxDenseIndex], wt[maxDenseIndex]) \
             or (Fraction(val[i], wt[i]) == Fraction(val[maxDenseIndex], wt[maxDenseIndex]) \
             and wt[i] < wt[maxDenseIndex] ):
                   
        maxDenseIndex = i
  
    dp = [0 for i in range(W + 1)]
  
    counter = 0
    breaked = False
    for i in range(W + 1):
        for j in range(len(wt)):
              
            if (wt[j] <= i):
                dp[i] = max(dp[i], dp[i - wt[j]] + val[j])
                  
        if i - wt[maxDenseIndex] >= 0 \
            and dp[i] - dp[i-wt[maxDenseIndex]] == val[maxDenseIndex]:
                  
            counter += 1
              
            if counter>= wt[maxDenseIndex]:
                  
                breaked = True
                # print(i)
                break
        else:
            counter = 0
  
    if not breaked:
        return dp[W]
    else:
        start = i - wt[maxDenseIndex] + 1
        times = (W - start) // wt[maxDenseIndex]
        index = (W - start) % wt[maxDenseIndex] + start
        return (times * val[maxDenseIndex] + dp[index])
          
          
# Driver Code
W = 100
val = [10, 30, 20]
wt = [5, 10, 15]
   
print(unboundedKnapsackBetter(W, val, wt))


输出:
300

时间复杂度:O( N + min(wt[i], W) * N)
辅助空间: O(W)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程。