Algorithm 两个值之和的增量最小的背包

Algorithm 两个值之和的增量最小的背包,algorithm,knapsack-problem,Algorithm,Knapsack Problem,这个问题是我在工作中实施某个系统时遇到的一个重新表述的问题。我认为这和背包问题有点相似,我很好奇如何解决它,因为我没能想出一个解决方案 问题陈述:给定一组物品,每个物品都有重量和价值,以及两个背包,确定要包含在这两个背包中的物品,使每个背包的重量正好为K,并且这两个背包的价值总和的增量尽可能小。如果两个背包都不可能满足权重约束,那么算法应该什么也不返回 我认为某种贪婪算法可能是一个令人满意的解决方案,但不确定如何编写它。这可以用动态规划方法解决。下面是一种使用链表的方法 from collect

这个问题是我在工作中实施某个系统时遇到的一个重新表述的问题。我认为这和背包问题有点相似,我很好奇如何解决它,因为我没能想出一个解决方案

问题陈述:给定一组物品,每个物品都有重量和价值,以及两个背包,确定要包含在这两个背包中的物品,使每个背包的重量正好为K,并且这两个背包的价值总和的增量尽可能小。如果两个背包都不可能满足权重约束,那么算法应该什么也不返回


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

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

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))
从集合导入namedtuple
ListEntry=namedtuple('ListEntry','id权重值prev')
Thing=namedtuple('Thing','weight value'))
def将条目添加到列表(即,e,l):
返回列表输入(i,l.weight+e.weight,l.value+e.value,l)
def分割_条目(条目、目标_权重):
空列表=列表输入(无、0、0、无)
dp_soln={(0,0):(空_列表,空_列表)}
对于范围内的i(len(条目)):
dp_soln_new={}
e=条目[i]
对于dp_soln.items()中的k,v:
(重量l,重量r)=k
(左左左右)=v
这个选项={k:v}
此_选项[(权重l+e.weight,权重r)]=(将_条目添加到_列表(即,e,l_左),l_右)
此_选项[(权重,权重+e.weight)]=(左侧,将_条目添加到_列表(即,右侧))
对于o_k,此_options.items()中的o_v:
如果目标重量<最大值(OK):
通过#不能导致(目标重量,目标重量)
elif o_k不在dp_soln_new中:
dp_soln_new[o_k]=o_v
其他:
diff=o_v[0]。值-o_v[1]。值
现有差异=dp_soln_new[o_k][0]。值-dp_soln_new[o_k][1]。值
如果现有_diff
这可以用动态规划方法解决。下面是一种使用链表的方法

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))
从集合导入namedtuple
ListEntry=namedtuple('ListEntry','id权重值prev')
Thing=namedtuple('Thing','weight value'))
def将条目添加到列表(即,e,l):
返回列表输入(i,l.weight+e.weight,l.value+e.value,l)
def分割_条目(条目、目标_权重):
空列表=列表输入(无、0、0、无)
dp_soln={(0,0):(空_列表,空_列表)}
对于范围内的i(len(条目)):
dp_soln_new={}
e=条目[i]
对于dp_soln.items()中的k,v:
(重量l,重量r)=k
(左左左右)=v
这个选项={k:v}
此_选项[(权重l+e.weight,权重r)]=(将_条目添加到_列表(即,e,l_左),l_右)
此_选项[(权重,权重+e.weight)]=(左侧,将_条目添加到_列表(即,右侧))
对于o_k,此_options.items()中的o_v:
如果目标重量<最大值(OK):
通过#不能导致(目标重量,目标重量)
elif o_k不在dp_soln_new中:
dp_soln_new[o_k]=o_v
其他:
diff=o_v[0]。值-o_v[1]。值
现有差异=dp_soln_new[o_k][0]。值-dp_soln_new[o_k][1]。值
如果现有_diff