提问人:Rudziankoŭ 提问时间:8/16/2022 最后编辑:user3386109Rudziankoŭ 更新时间:8/17/2022 访问量:87
带权重的位掩码
Bitmask with weights
问:
我有以下几对:
pairs = [(1,9),(5,5),(6,4),(2,8)]
从这对中,我只能选择一个元素。我需要生成 n 个总和最小的二进制掩码组合列表,其中第一个元素和第二个元素。0
1
如果 n == 5,则提供示例的输出:
[0,0,1,0], [0,1,1,0], [0,0,0,0], [0,1,0,0], [0,0,1,1]
是背包问题吗?执行此操作的最佳算法是什么?
答:
3赞
David Eisenstat
8/16/2022
#1
下面代码背后的想法是枚举排序后的组合 递归(好吧,不使用递归)作为对列表的尾部, 然后在使用较小 元素和使用较大 元素。空间需求最小化 发生器(一般应按元件数量量级排列 你拿)。
import collections
import itertools
def extend_sorted(pair, sequence):
argmin_pair = min(range(2), key=pair.__getitem__)
min_pair = pair[argmin_pair]
argmax_pair = 1 - argmin_pair
max_pair = pair[argmax_pair]
buffer = collections.deque()
for sub_combo, sub_total in sequence:
while buffer and buffer[0][1] < min_pair + sub_total:
yield buffer.popleft()
yield ([argmin_pair] + sub_combo, min_pair + sub_total)
buffer.append(([argmax_pair] + sub_combo, max_pair + sub_total))
while buffer:
yield buffer.popleft()
def enumerate_least_sums(pairs):
sequence = [([], 0)]
for pair in reversed(pairs):
sequence = extend_sorted(pair, sequence)
for combo, total in sequence:
yield combo
if __name__ == "__main__":
print(*itertools.islice(enumerate_least_sums([(1, 9), (5, 5), (6, 4), (2, 8)]), 5))
输出:
[0, 0, 1, 0] [0, 1, 1, 0] [0, 0, 0, 0] [0, 1, 0, 0] [0, 0, 1, 1]
评论
0赞
Rudziankoŭ
8/17/2022
谢谢你的回答。有几个问题:1)您能评论一下发电机是如何工作的吗?它有 3 个产量选项,我不明白我们在什么情况下使用它们中的每一个。2) 我也不明白你是如何保持掩码长度的,在同一个我们有不同的长度的情况下,我们最终会得到正确长度的 len(pairs),从来没有明确等待过它。extend_sorted
buffer
sequence
0赞
David Eisenstat
8/17/2022
@Rudziankoŭ 第一和第三产量发射使用最大值的掩码;第二个产量发出使用 min.缓冲区包含使用最大值的掩码,我们已经用最小值发出了相应的掩码。我们排空下一个最小掩码之前的 max-masks,然后发出 min-mask。最后,我们发出剩余的最大掩码。
下一个:N种有序二进制掩码排列
评论
[0,0,1,0], [0,1,1,0], [0,0,0,0]
0,0,1,0
0,1,1,0
0,0,0,0
n=3