【问题标题】:Two knapsacks with smallest delta in sum of values两个值之和最小的背包
【发布时间】:2020-07-02 21:20:38
【问题描述】:

这个问题是我在工作中实施某些系统时遇到的一个改写的问题。我认为这与背包问题有点相似,并且好奇地探索如何解决它,因为我无法提出解决方案。

问题陈述:给定一组物品,每个物品都有重量和价值,以及两个背包,确定哪些物品要包含在这两个背包中,因此每个背包的重量恰好为 K 和这些物品的值之和的增量两个背包越小越好。如果不能满足两个背包的重量约束,算法应该什么都不返回。

我认为某种贪心算法可能是一个令人满意的解决方案,但不知道如何编写它。

【问题讨论】:

    标签: algorithm knapsack-problem


    【解决方案1】:

    这可以通过动态规划方法解决。这是一种使用链表的方法。

    from collections import namedtuple
    
    ListEntry = namedtuple('ListEntry', 'id weight value prev')
    Thing = namedtuple('Thing', 'weight value')
    
    def add_entry_to_list(i, e, l):
        return ListEntry(i, l.weight + e.weight, l.value + e.value, l)
    
    def split_entries (entries, target_weight):
        empty_list = ListEntry(None, 0, 0, None)
        dp_soln = { (0, 0): (empty_list, empty_list) }
    
        for i in range(len(entries)):
            dp_soln_new = {}
            e = entries[i]
            for k, v in dp_soln.items():
                (weight_l, weight_r) = k
                (l_left, l_right) = v
    
                this_options = {k: v}
                this_options[(weight_l + e.weight, weight_r)] = (add_entry_to_list(i, e, l_left), l_right)
                this_options[(weight_l, weight_r + e.weight)] = (l_left, add_entry_to_list(i, e, l_right))
    
                for o_k, o_v in this_options.items():
                    if target_weight < max(o_k):
                        pass # Can't lead to (target_weight, target_weight)
                    elif o_k not in dp_soln_new:
                        dp_soln_new[o_k] = o_v
                    else:
                        diff = o_v[0].value - o_v[1].value
                        existing_diff = dp_soln_new[o_k][0].value - dp_soln_new[o_k][1].value
                        if existing_diff < diff:
                            dp_soln_new[o_k] = o_v
            dp_soln = dp_soln_new
    
        final_key = (target_weight, target_weight)
        if final_key in dp_soln:
            return dp_soln[final_key]
        else:
            return None
    
    print(split_entries([
        Thing(1, 3),
        Thing(1, 4),
        Thing(2, 1),
        Thing(2, 5),
        ], 3))
    

    【讨论】:

      猜你喜欢
      • 2018-11-15
      • 2019-01-26
      • 1970-01-01
      • 2011-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-14
      • 1970-01-01
      相关资源
      最近更新 更多