两个背包的值之和具有最小的 delta
Two knapsacks with smallest delta in sum of values
这个问题是我在工作中实现某个系统时遇到的改写问题。我认为这有点类似于背包问题,并且很好奇地探索如何解决它,因为我无法提出解决方案。
问题陈述:给定一组物品,每个物品都有重量和价值,还有两个背包,确定哪些物品要包含在这两个背包中,这样每个背包的重量正好是 K 和价值总和的增量这两个背包越小越好。如果不可能满足两个背包算法的重量约束应该 return 没有。
我认为某种贪心算法可能是一个令人满意的解决方案,但不确定如何编写它。
这可以用动态规划的方法来解决。这是一种使用链表的方法。
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))
这个问题是我在工作中实现某个系统时遇到的改写问题。我认为这有点类似于背包问题,并且很好奇地探索如何解决它,因为我无法提出解决方案。
问题陈述:给定一组物品,每个物品都有重量和价值,还有两个背包,确定哪些物品要包含在这两个背包中,这样每个背包的重量正好是 K 和价值总和的增量这两个背包越小越好。如果不可能满足两个背包算法的重量约束应该 return 没有。
我认为某种贪心算法可能是一个令人满意的解决方案,但不确定如何编写它。
这可以用动态规划的方法来解决。这是一种使用链表的方法。
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))