【问题标题】:Knapsack with two sums and two sets有两个和两个集合的背包
【发布时间】:2022-01-14 03:40:52
【问题描述】:

对于算法作业,我被要求给出一个背包问题的解决方案。我输入了一个产品列表。一种产品被分配了一个成本和一些卡路里。所以我有两套,一套钱,一套大卡。我的目标是选择能提供等量金钱和千卡的产品。

例如,如果我有这个输入:(1, 3), (2, 4), (5, 8), (4, 5)

货币总和等于 m=7 和 kcal 总和等于 k=12,我需要选择完全满足这两个总和的产品。在我的示例中,我将选择产品 (2, 4) 和 (5, 8)。我的解决方案只需要在存在符合要求的产品时返回true,否则返回false。无需退货一套产品

我已经编写了一个基于子集问题的递归解决方案,我记得我的函数是否使用最后一个产品。此解决方案有效,但速度太慢 -> 2^n。

def isSubsetSum(set, n, sum, set2, sum2):
    if (sum == 0 and sum2==0):
        return True
    if (n == 0 or (sum < 0 or sum2 < 0)):
        return False
        
    if (set[n] > sum) or (set2[n] > sum2):              # if one of the two values (money, calories) is bigger than the sum 
        return isSubsetSum(set, n-1, sum, set2, sum2)   # we avoid using this product -> recall with n-1

    inclusion = isSubsetSum(set, n-1, sum-set[n], set2, sum2-set2[n]) # we recurse includig the last product
    exclusion = isSubsetSum(set, n-1, sum, set2, sum2)  # we recurse excluding the last product

return inclusion or exclusion

我试图将我的子集函数更改为动态编程方法,但我很难将我的函数更改为使用两组(一组钱和一组卡路里)。

我与助教交谈,他们指导我选择背包问题而不是子集和问题。我看到了背包动态编程方法的原理,但是在将问题更改为使用我的输入时,我遇到了与之前使用子集相同的问题。

我想我遗漏了一些东西,如果你能帮助我理解我错在哪里,那就太好了。

谢谢

【问题讨论】:

    标签: python dynamic-programming


    【解决方案1】:

    下面是动态编程方法的样子:

    import numpy as np
    
    M = 7 
    K = 12
    products = [(1, 3), (2, 4), (5, 8), (4, 5)]
    
    # For an empty list of products, only the problem with m=k=0 is solvable:
    solvable = np.zeros(shape=(M + 1, K + 1), dtype=bool)
    solvable[0, 0] = True
    
    def one_more(product, solvable):
        result = solvable.copy()
        m_inc, k_inc = product
        for m in range(m_inc, M + 1):
            for k in range(k_inc, K + 1):
                if not solvable[m, k]:
                    result[m, k] = solvable[m - m_inc, k - k_inc]
        return result
    
    for product in products:
        solvable = one_more(product, solvable)
    
    # The full problem of interest:
    print(solvable[M, K])
    

    NumPy 在这里很有用,因为它提供了一个二维数组数据结构,但使用嵌套列表也可以达到同样的效果。

    我们从目标值MK 作为常量和给定的产品列表开始。关键思想是迭代产品列表,从 0 个产品开始,一次添加一个产品,每次更新一个矩阵 (solvable),该矩阵指示哪些子问题对于给定的部分问题列表是可解决的。

    更具体地说,如果 m=i 和 k=j 的问题可以通过当前的部分产品列表解决,solvable[i, j] 为 True。

    函数one_more() 更新solvable 矩阵以添加更多可用产品。如果 m 和 k 减少了新产品的值的子问题已经可以解决,那么没有这个新产品就无法解决的子问题变得可解决。

    一旦我们用所有产品更新了solvable,我们就可以在这个矩阵的右下角查找感兴趣的解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-23
      • 2014-05-29
      • 1970-01-01
      相关资源
      最近更新 更多