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