Ответ 1
Тот факт, что порядок разложения не имеет для вас значения, делает его намного сложнее. То есть вы просматриваете {2 2} U {2 3}
так же, как {2 3} U {2 2}
. Тем не менее, у меня есть алгоритм, который лучше, чем у вас, но он невелик.
Позвольте мне начать с реалистично сложного примера. Наш набор будет A B C D E F F F F G G G G
. Раздел будет 1 1 1 1 2 2 5
.
Мое первое упрощение будет состоять в том, чтобы представить информацию, которая нам нужна в наборе с структурой данных [[2, 4], [5, 1]]
, что означает, что 2 элемента повторяются 4 раза, а 5 повторяются один раз.
Мое второе кажущееся усложнение будет представлять раздел с [[5, 1, 1], [2, 2, 1], [4, 1, 1]
. Образец может быть не очевидным. Каждая запись имеет вид [size, count, frequency]
. Таким образом, один отдельный экземпляр из 2 разделов размера 2 превращается в [2, 2, 1]
. Мы пока не используем частоту, но это подсчет различимых грудов одинакового размера и общей общности.
Теперь мы займемся следующим образом. Мы рассмотрим наиболее общий элемент и найдем все способы его использования. Поэтому в нашем случае мы берем одну из кучек размера 4 и обнаруживаем, что мы можем разделить ее следующим образом, переставляя каждую оставшуюся стратегию раздела в лексикографическом порядке:
-
[4]
, оставляя[[1, 1, 1], [2, 2, 1], [1, 4, 1]] = [[2, 2, 1], [1, 4, 1], [1, 1, 1]]
. -
[3, [1, 0], 0]
оставить[[2, 1, 1], [1, 1, 1], [2, 1, 1], [1, 4, 1]] = [[2, 1, 2], [1, 4, 1], [1, 1, 1]
. (Обратите внимание, что мы используем частоту.) -
[3, 0, 1]
оставить[[2, 1, 1], [2, 2, 1], [0, 1, 1], [1, 3, 1]] = [[2, 2, 1], [2, 1, 1], [1, 3, 1]]
-
[2, [2, 0], 0]
оставить[[3, 1, 1], [0, 1, 1], [2, 1, 1], [1, 4, 1]] = [[3, 1, 1], [2, 1, 1], [1, 4, 1]]
-
[2, [1, 1], 0]
оставить[[3, 1, 1], [1, 2, 1], [1, 4, 1]] = [[3, 1, 1], [1, 4, 1], [1, 2, 1]]
-
[2, [1, 0], [1]]
оставить[[3, 1, 1], [1, 1, 1], [2, 1, 1], [0, 1, 1], [1, 3, 1]] = [[3, 1, 1], [2, 1, 1], [1, 4, 1], [1, 1, 1]]
-
[2, 0, [1, 1]]
, оставляя `[[3, 1, 1], [2, 2, 1], [0, 2, 1], [1, 2, 1]] = [[3, 1, 1], [2, 2, 1], [1, 2, 1]] 1 -
[1, [2, 1]]
оставить[[4, 1, 1], [0, 1, 1], [1, 1, 1], [1, 4, 1]] = [[4, 1, 1], [1, 4, 1], [1, 1, 1]]
-
[1, [2, 0], [1]]
оставить[[4, 1, 1], [0, 1, 1], [2, 1, 1], [0, 1, 1], [1, 3, 1]] = [[4, 1, 1], [2, 1, 1], [1, 3, 1]]
-
[1, [1, 0], [1, 1]]
оставить[[4, 1, 1], [1, 1, 1], [2, 1, 1], [0, 2, 1], [1, 2, 1]] = [[4, 1, 1], [2, 1, 1], [1, 2, 1], [1, 1, 1]]
-
[1, 0, [1, 1, 1]]
оставить[[4, 1, 1], [2, 2, 1], [0, 3, 1], [1, 1, 1]] = [[4, 1, 1], [2, 2, 1], [1, 1, 1]]
-
[0, [2, 2]]
оставить[[5, 1, 1], [0, 2, 1], [1, 4, 1]] = [[5, 1, 1], [1, 4, 1]]
-
[0, [2, 1], [1]]
оставить[[5, 1, 1], [0, 1, 1], [1, 1, 1], [0, 1, 1], [1, 3, 1]] = [[5, 1, 1], [1, 3, 1], [1, 1, 1]]
-
[0, [2, 0], [1, 1]]
оставить[[5, 1, 1], [0, 2, 1], [2, 1, 1], [0, 2, 1], [1, 2, 1]] = [[5, 1, 1], [2, 1, 1], [1, 2, 1]]
-
[0, [1, 1], [1, 1]]
оставить[[5, 1, 1], [1, 2, 1], [0, 2, 1], [1, 2, 1]] = [[5, 1, 1,], [1, 2, 2]]
-
[0, [1, 0], [1, 1, 1]]
оставить[[5, 1, 1], [1, 1, 1], [2, 1, 1], [0, 3, 1], [1, 1, 1]] = [[5, 1, 1], [2, 1, 1], [1, 1, 2]]
-
[0, 0, [1, 1, 1, 1]]
оставить[[5, 1, 1], [2, 2, 1], [0, 4, 1]] = [[5, 1, 1], [2, 2, 1]]
Теперь каждая из этих подзадач может быть рекурсивно решена. Это может показаться, что мы на пути к их созданию, но мы этого не делаем, потому что мы memoize рекурсивные шаги. Оказывается, существует много способов, которыми первые две группы из 8 могут закончиться с теми же 5 оставленными. С memoization нам не нужно многократно пересчитывать эти решения.
Тем не менее, мы сделаем лучше. Группы из 12 элементов не должны создавать проблемы. Но мы не делаем этого намного лучше. Я не удивлюсь, если он начнет разрушаться где-то вокруг групп из 30 элементов с интересными наборами разделов. (Я не закодировал его. Это может быть нормально в 30 и сломаться на 50. Я не знаю, где он сломается. Но, учитывая, что вы повторяете множество разделов, в какой-то довольно небольшой точке это будет сломайте.)