【问题标题】:Can't figure out how to solve this knapsack problem不知道如何解决这个背包问题
【发布时间】:2020-01-19 22:01:29
【问题描述】:

我正在尝试解决这个背包问题的例子:

一艘船必须用不同重量的容器包装 并且有不同的价值观。任务是找到最优的 容器(0-9)的组合以获得最大的价值,同时仍然 体重限制在320以内。

我无法弄清楚如何将容器与我目前拥有的代码进行这种最佳组合。我似乎无法获得任何结果来帮助我找到代码中的错误或帮助我了解缺少的内容。

weight = [50, 50, 60, 80, 100, 110, 120, 150, 150, 200]
value    = [80, 80, 60, 50, 100,  90, 100, 170, 200, 240]
n = len(weight)
max_w = 320



def build_items(n):
    res = []
    for i in range(n):
        items = (weight[i], value[i])
        res.append(items)
    return res

def powerset(items):
    res = [[]]
    for item in items:
        newset = [r+[item] for r in res]
        res.extend(newset)
    return res

def kbf(items, max_weight):
    knapsack = []
    best_weight = 0
    best_value = 0
    for item_set in powerset(items):
        set_weight = sum(e[0] for e in item_set)
        set_value = sum(e[1] for e in item_set)
        if set_value > best_value and set_weight <= max_w:
            best_value = set_value
            best_weight = set_weight
            knapsack = item_set
        return knapsack, best_weight, best_value


data = build_items(n)
print(data)
print(powerset(data))
print(kbf(data,max_w))

打印最后一个函数给了我一个非常奇怪的输出。

【问题讨论】:

  • “奇怪的输出”是什么意思?它有什么奇怪的?你期待什么?

标签: python knapsack-problem


【解决方案1】:

您应该研究像 scipy.optimize (https://docs.scipy.org/doc/scipy-0.18.1/reference/tutorial/optimize.html) 和 gurobipy 这样的线性编程包,因为您需要代数来正确建模问题,然后实现像单纯形这样的内置算法来解决它。在您的情况下,您需要一个整数线性公式,因为结果是一个整数。因此,例如,您希望最大化价值max(v),其中 v 是所有选择的项目的总和 maximize sum(vi*xi) for i in range(0,9),x 是二进制表示该项目是否包含 c1 = x in (0,1)。这个问题的第二个限制是每个项目的相对权重之和必须小于 320,所以c2 = sum(wi*xi) for i in range(0,9) &lt;= 320。要最大化单纯形中的函数,请最小化负函数 (Maximize objective function using scipy.optimize)。

【讨论】:

    【解决方案2】:

    这是一个二维背包问题的经典例子,它可以通过两个嵌套循环和一个 (n+1) x (W+1) 维 DP 表(动态规划)快速解决

    DP[x,y] = n x W Table, DP[0,x] = 0 for all x, DP[y,0] = 0 for all y
    
    W = 320
    weight = [0....n-1]
    value = [0....n-1]
    
    for(i from i=1 to i=n):
        for(w from w=0 to =W):
            if w == 0:
                DP[i,0] = 0
                continue     
            if weight[i] > w:
                DP[i,w] = DP[i-1,w]
                continue
            DP[i,w] = max(DP[i-1,w],DP[i-1,w-weight[i]+value[i])
    return DP[n,W]
    

    虽然我不能向您保证,实施这个确切的伪代码会使其正常工作,但这是解决此类问题的一般结构。困难始终在于根据已经进行的基础计算确定哪些变量可用于计算条目。




    您可能想查看Wikipedia about knapsack 以获取更多建议,这种确切类型问题的示例代码非常简洁。

    【讨论】:

    • 很抱歉坚持你,但我想给你一个“up”,我想我找到了。同样,这样的答案可能会提供指向外部资源的链接,并且 OP 可以根据该资源解决他的问题,但 SO 标准是至少在答案中提供足够的信息,以便找到正确的解决方案(即解释问题)。使用指向外部资源的链接作为“更多信息”或“如此链接所述,您可以执行 XYZ”的一部分。没有必要提供一个很好的答案(就像我这样做并且有一些理由这样做)来提供一个好的答案。
    • 我不介意有你在身边,感谢您的指导/建议,我仍在试图找出什么是广泛的答案的良好中间立场,我想这会有所帮助。
    • 我只是有一种感觉,如果我没有明确指出该问题中的所有代码缺陷,它可能会导致 OP 提出更多问题,而所有这些问题都只是由于缺乏知识.并非所有问题都与家庭作业/作业有关,但请看一下:meta.stackoverflow.com/questions/334822/… 我认为它可以为您提供一些关于回答的想法(并尝试查看 meta 上投票最多的问题,其中一些问题也为良好的答案提供了很好的信息接近
    • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
    • 刚刚阅读了 meta 并得到了这个 meta.stackoverflow.com/questions/350305/… 作为回报,所以最终的答案 - 这一切都取决于......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-22
    • 1970-01-01
    • 2021-09-15
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    相关资源
    最近更新 更多