Основная идея такова: при определении того, что находится в строке 3, вам не важно, что находится в строке 1, а только то, что в строке 2.
Итак, давайте назовем, как построить слой 64x1, «сценарий строки». Вы говорите, что существует около 3300 сценариев строк. Это не так уж плохо.
Давайте вычислим функцию:
f (s, r) = количество способов поместить номер сценария строки "s" в строку "r" и законно заполнить все строки выше "r".
(я считаю со строкой "1" вверху и строкой "10" снизу)
Хватит читать сейчас, если вы хотите избежать спойлеров.
Теперь ясно (нумерация строк от 1 до 10):
f (s, 1) = 1
для всех значений "s".
Кроме того, и здесь начинается понимание (с использованием Mathematica -ish нотации)
f(s, r) = Sum[ f(i, r-1) * fits(s, i) , {i, 1, 3328} ]
где «соответствует» - это функция, которая принимает два номера сценария и возвращает «1», если вы можете легально сложить эти две строки друг над другом, и «0», если не можете. При этом используется понимание, поскольку число законных способов размещения сценария зависит только от количества способов размещения сценариев над ним, которые совместимы в соответствии с «подгонками».
Теперь подгонки могут быть предварительно вычислены и сохранены в массиве байтов 3328 на 3328. Это всего около 10 мегабайт памяти. (Меньше, если вы захотите сохранить его как битовый массив)
Тогда ответ, очевидно, просто
Sum[ f(i, 10) , {i, 1, 3328} ]