如何实现回溯打印背包中的物品(允许重复物品)?

Posted

技术标签:

【中文标题】如何实现回溯打印背包中的物品(允许重复物品)?【英文标题】:How to implement backtracking to print the items taken in knapsack(repetition of items allowed)? 【发布时间】:2018-08-23 22:38:02 【问题描述】:

我有这个列表:

[['0', 'Cool Blue Marella Jug', '33', '15'],
 ['1', 'Weight Loss Pack', '55', '16'],
 ['2', 'Natural Black Vogue Lashes', '10', '6'],
 ['3', 'Paris Age Perfect Intense Nutrition Serum', '45', '22']​
  ...]
第一个数字是产品ID, 第二个数字 (55,10,...) 是价格和 第三个数字 (16,6...) 是利润。

使用下面的代码,如果我输入价格限制,我应该通过最好的商品组合获得最高利润(商品可以多次出售)。

这是我的代码:

def dp_pricelimit(product_list, price_limit):
    #to store results
    chosenProduct=[0]*(price_limit+1)
    memo=[0]*(price_limit+1)
    memo[0]=0
    for price in range(1, price_limit+1):
        for item in product_list:#go through the items
            if item[2]<=price:
                balance=price-item[2]
                profit=item[3] + memo[balance]
                if profit>memo[price]:#if found new optimal
                    memo[price]=profit
                    chosenProduct[price]=item[0]

    return memo[price_limit],chosenProduct

现在我需要对其进行修改,使其还返回一个列表chosenProduct,代表所选要出售的产品 ID。

例如​如果产品cool blue marella jug被选择了两次并且减肥包被选择了一次列表应该是,chosenProduct=[0,0,1]

每当我找到一个新的最优值时,我都会尝试将选择的产品存储在一个列表中,但它会存储从值 1 到 price_limit 的每个最优值。我希望它只存储选择的最新产品,并从那里使用回溯来列出所有选择的构成利润的产品。我该怎么做?

【问题讨论】:

欢迎来到 ***。请按照您创建此帐户时的建议阅读并遵循帮助文档中的发布指南。 Minimal, complete, verifiable example 适用于此。在您发布 MCVE 代码并准确描述问题之前,我们无法有效地帮助您。我们应该能够将您发布的代码粘贴到文本文件中并重现您描述的问题。 您发布的代码在尝试比较 int 和 string 类型时会死掉。在我修复它之后,我发现它只选择一个项目,无论价格如何。我认为您的下一步是完成有关递归和回溯的教程,因此您将找到有效的答案。 那么你就可以担心跟踪购物清单了。 【参考方案1】:
def dp_pricelimit(product_list, price_limit):
    #to store results
    chosenProduct=[None]*(price_limit+1)
    memo=[0]*(price_limit+1)
    memo[0]=0
    for price in range(1, price_limit+1):
        for item in product_list:#go through the items
            if item[2]<=price:
                balance=price-item[2]

                profit=item[3] + memo[balance]
                if profit>memo[price]:#if found new optimal
                    memo[price]=profit
                    chosenProduct[price]=item[0]

    #use list to store list of item
    items = []
    #set i, the current price, to max price
    i = price_limit

    #while i is not a negative price
    while i >= 0:
        if chosenProduct[i] == None:
            break
        #append the item that was last added to make the optimal profit at price i.
        items.append(chosenProduct[i])
        #then jump back to before we added this item by decrementing the i, the current price, by the price of the last item that was added.
        i-=product_list[items[-1]][2]




    return memo[price_limit],items


print(dp_pricelimit([[0, 'Cool Blue Marella Jug', 33, 15],[1, 'Weight Loss Pack', 55, 16], [2, 'Natural Black Vogue Lashes', 10, 2], [3, 'Paris Age Perfect Intense Nutrition Serum', 45, 22]],88))

基本上,使用 selectedproduct 数组向后迭代。添加的最后一项以创建最佳;可以减去它的成本,以在添加之前的价格获得最优值。然后在下一个价格处,我们添加了最后一项以在 selectedproduct 数组中获取当前价格。祝你好运;)

【讨论】:

另外,您可能希望将利润变量更改为收入。 好的,谢谢,但我只是想知道为什么我们在 i-=product_list[items[-1]][2] 处需要 [2]?我试过没有它并且不支持的操作数类型-=: 'int' 和 'list'?[2] 是指价格吗? 所以 [2] 是该特定商品的价格指数。所以 product_list[items[-1]] 代表一个项目, product_list[items[-1]][2] 是那个项目的价格。 items[-1] 还表示 items 数组(这是一个项目 ID 列表)中的最后一个元素(也是最后一个附加元素),我们使用 product_list 作为给定项目 ID 号的项目其余信息的查找表.

以上是关于如何实现回溯打印背包中的物品(允许重复物品)?的主要内容,如果未能解决你的问题,请参考以下文章

0-1背包问题的回溯法代码

回溯算法背包问题(Java版)

0-1背包问题 —— 四种解法解题

0-1背包-回溯法

动态规划中的0-1背包问题怎么去理解?要求给出具体实例和详细步骤。。。

0-1背包回溯