带权重的位掩码

Bitmask with weights

提问人:Rudziankoŭ 提问时间:8/16/2022 最后编辑:user3386109Rudziankoŭ 更新时间:8/17/2022 访问量:87

问:

我有以下几对:

pairs = [(1,9),(5,5),(6,4),(2,8)]

从这对中,我只能选择一个元素。我需要生成 n 个总和最小的二进制掩码组合列表,其中第一个元素和第二个元素。01

如果 n == 5,则提供示例的输出:
[0,0,1,0], [0,1,1,0], [0,0,0,0], [0,1,0,0], [0,0,1,1]

背包问题吗?执行此操作的最佳算法是什么?

Python 算法 与语言无关

评论

0赞 Mitchnoff 8/16/2022
为了确保我理解,例如,如果你有 n=3,你会有 [0, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0] 和 [0, 0, 1, 1] ?
0赞 Ted Lyngmo 8/16/2022
@Mitchnoff 不,这些是总和最小的组合。 总和最小,第二小,第三小。[0,0,1,0], [0,1,1,0], [0,0,0,0]0,0,1,00,1,1,00,0,0,0
0赞 Mitchnoff 8/16/2022
@TedLyngmo为什么只有这 3 个?
0赞 Ted Lyngmo 8/16/2022
@Mitchnoff 你要求.n=3
0赞 Mitchnoff 8/16/2022
@TedLyngmo是的,我的意思是为什么当 n=3 时你最终会得到这 3 个列表

答:

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_sortedbuffersequence
0赞 David Eisenstat 8/17/2022
@Rudziankoŭ 第一和第三产量发射使用最大值的掩码;第二个产量发出使用 min.缓冲区包含使用最大值的掩码,我们已经用最小值发出了相应的掩码。我们排空下一个最小掩码之前的 max-masks,然后发出 min-mask。最后,我们发出剩余的最大掩码。