最大组合总和(算法优化)

时间:2018-03-07 01:17:43

标签: algorithm

我有一个长度为 n 的字典选择 m ,其长度为 m 的元组的键包含整数1到名词的。我想计算这个字典值的最大总和,使得元组键的索引是唯一的,存储组成这个最大值的组合。

示例输入:

input_dict = {
    (1, 2): 16,
    (1, 3): 4,
    (1, 4): 13,
    (1, 5): 8,
    (1, 6): 9,
    (2, 3): 6,
    (2, 4): 19,
    (2, 5): 7,
    (2, 6): 16,
    (3, 4): 12,
    (3, 5): 23,
    (3, 6): 12,
    (4, 5): 17,
    (4, 6): 19,
    (5, 6): 21
}

示例输出:

(((1, 2), (3, 5), (4, 6)), 58)

我目前的方法:计算所有独特输出组合的总和并取最大值。

gen_results = [{}]

for (key, val) in input_dict.items():
    gen_results[0][(key,)] = val

i = 0
complete = False
while not complete:
    complete = True
    gen_results.append({})
    for (combinations, running_sum) in gen_results[i].items():
        for (key, val) in input_dict.items():
            unique_combination = True
            for combination in combinations:
                for idx in key:
                    if idx in combination:
                        unique_combination = False
                        break
                if not unique_combination:
                    break
            if unique_combination:
                complete = False
                gen_results[i+1][combinations + (key,)] = running_sum + val
    i += 1

generation_maximums = []
for gen_result in gen_results:
    if gen_result == {}:
        continue
    generation_maximums.append(max(gen_result.items(), key=(lambda x: x[1])))

print(max(generation_maximums, key=(lambda x: x[1])))

如何改进大型 n m 的算法?

1 个答案:

答案 0 :(得分:0)

如果你不进行整数编程,你通常可以使用位作为哈希来强制使用这些东西

e.g。以下输出58

input_dict = {
    (1, 2): 16,
    (1, 3): 4,
    (1, 4): 13,
    (1, 5): 8,
    (1, 6): 9,
    (2, 3): 6,
    (2, 4): 19,
    (2, 5): 7,
    (2, 6): 16,
    (3, 4): 12,
    (3, 5): 23,
    (3, 6): 12,
    (4, 5): 17,
    (4, 6): 19,
    (5, 6): 21
}
dp = {}
n, m = 2, 6
for group, score in input_dict.items():
    bit_hash = 0
    for x in group:
        bit_hash += 1 << (x-1)
    dp[bit_hash] = score

while True:
    items = dp.items()
    for hash1, score1 in items:
        for hash2, score2 in items:
            if hash1 & hash2 == 0:
                dp[hash1|hash2] = max(dp.get(hash1|hash2), score1+score2)
    if len(dp) == (1<<m)/2-1:
        print dp[(1<<m)-1]
        break