Эта проблема является NP-полной, поэтому, если P = NP, вы застряли, выполняя экспоненциальную работу над размером ввода. Теперь в этом типе проблемы есть то, что на самом деле есть два способа решения, которые позволят выразить различные аспекты проблемы.
Во-первых, если в ваших суммах не слишком много элементов, вы можете просто перебрать эту проблему, выполнив поиск по всем комбинациям. Этот метод экспоненциально зависит от количества элементов в наборах и будет работать достаточно хорошо, скажем, около 20 элементов на контейнер. После этого все станет довольно неприятно.
Второй вариант - использовать динамическое программирование. В отличие от предыдущего метода, этот алгоритм экспоненциально по количеству битов, которое требуется для записи каждого из чисел. Что вы делаете, это отслеживает набор всех возможных сумм, а также наименьшее количество элементов, необходимых для их генерации. Это простая модификация решения, которое вы указали в своем ответе.
Вот код Python, который генерирует все возможные значения, в которых они могут пересекаться:
def gen_sum(a):
r = { 0: [] }
for x in a:
for y, v in r.items():
if not (x+y) in r or len(r[x+y]) > len(v) + 1:
r[x+y] = v + [x]
return r
def gen_sums(a, b):
asum = gen_sum(a)
bsum = gen_sum(b)
return [ (k, v, bsum[k]) for k,v in asum.items() if k in bsum ][1:]
Запустив его на ваших образцах данных, я получил:
[(4000, [4000], [2000, 2000]), (6000, [2000, 4000], [565, 1435, 2000, 2000]), (2000, [2000], [2000]), (4200, [200, 4000], [528, 800, 2872]), (10200, [200, 2000, 2000, 2000, 4000], [528, 565, 800, 1435, 2000, 2000, 2872]), (8200, [200, 2000, 2000, 4000], [528, 800, 2000, 2000, 2872]), (6200, [200, 2000, 4000], [528, 800, 2000, 2872])]
РЕДАКТИРОВАТЬ: Исправлена опечатка, а также только что заметил, что святые дерьмо тонны людей уже ответили на это очень быстро.