Алгоритм пытается последовательно поместить полимино одно за другим в таблицу. Если на каком-то этапе поставить полиомино не удаётся, возвращаемся на предыдущий этап и пытаемся там поставить полиомино в другое положение, затем опять идём дальше (или возвращаемся ещё на один этап назад) и т.д.
Программа достаточно оптимальна по памяти и используемым ресурсам. В качестве основной структуры данных для манипуляций c объектами используются NumPy массивы (тип элементов int64). Полиомино кодируются матрицами. За начало координат берётся левый верхний угол прямоугольника, ось ординат направлена вниз. Затем к матрицам применяются преобразования сдвига и поворота.
Для подбора замощения применяются генераторы, это также сильно экономит память, позволяет не использовать рекурсию (что может переполнить стек вызовов) и позволяет не запоминать специально состояния, а также уже рассмотренные комбинации.
Таким образом, по памяти оценка будет порядка
(сумма размерностей всех полиомино + сумма размерностей L-полиомино + размерность таблицы*(количество полиомино и L-полиомино))*8 байт. То есть O(n)
, где n
- количество всех полиомино и L-полиомино при константной таблице.
По сложности алгоритм в худшем случае будет пропорционален
(4М_1М_2)^(H_1+H_2)
. Таким образом, в общем случае будет экспоненциальная сложность. На сколько я понял из описаний в интернете, данная проблема в общем случае является NP
сложной [1], так что такая оценка вполне ожидаема.
Из вариантов решения можно также предложить генетические алогоритмы, например, с использованием модулей pyeasyga
или DEAP
[2, 4].
Программа запускалась в среде
- Ubuntu 20.10 (Linux 5.8.0-50-generic x86_64 GNU/Linux)
- Python 3.8.6
- numpy 1.20.2
а также в Docker-контейнере c
- Linux Alpine 3.12
- Python 3.9.4
- numpy 1.20.2.
- Устанавливаем виртуальное окружение
virtualenv env
- Активируем окружение
. ./env/bin/activate
- Устанавливаем модули Python
pip install -r requirements.txt
- В файле
example1.py
параметры считываются из файлаparameters.txt
. В соответствии с заданием параметры следующие:
- первая строка — тапл-пара с размером прямоугольника
- вторая строка -
H_1
- количество полиомино - на следующих строках указывается сначала мощность полиомино-множества, порожденного соответствующим прямоугольником-полоимино как опорным, затем тапл-пара — размер порождающего полиомино.
- затем аналогично для L-полиомино.
-
В файле
example2.py
совокупность полиомино определяется непосрественно в коде (с немного другими данными). -
Запуск
python example1.py
python example2.py
- Создаём Docker образ
docker build -t poliominos .
- Запускаем контейнер
docker run --rm poliominos
docker run --rm vol1ura/poliominos
- Голомб С.В. Полимино \Пер. с англ. В. Фирсова — Москва: Мир, 1975 - с.207.
- https://pyeasyga.readthedocs.io/
- https://habr.com/ru/post/498308/
- https://deap.readthedocs.io/en/master/examples/
- https://habr.com/ru/post/501008/
- https://habr.com/ru/post/408299/
- https://www-cs-faculty.stanford.edu/~knuth/programs.html
- https://www.ugatu.su/media/uploads/MainSite/Science/dissovet/03/2014/ChirikovHY/autoref.pdf