Как сгенерировать домино-плитку квадрата?

Краткое описание:

Я пытаюсь создать плитки квадрата с домино или, другими словами, с плитками 2x1 и 1x2.

Иногда мой алгоритм размещает вертикальную плитку таким образом, что невозможно заполнить последнюю строку.

Мой текущий подход состоит в том, чтобы инициализировать сетку нулями (скажем, сетку 8x8). Я представляю левую половину горизонтальной плитки с 1 и правую половину с 2 в сетке.

Соответственно, верхняя половина вертикальной плитки равна 3, а нижняя половина — 4.

Затем я просматриваю каждую строку сетки слева направо и там, где 0, я помещаю плитку:

  • Всякий раз, когда я нахожусь на правом краю сетки или пространство справа не равно 0, я кладу вертикальную плитку (3).
  • Когда я на нижнем краю, я (могу) класть только горизонтальные плитки.
  • Когда ни один из вышеперечисленных не установил значение, я ставлю случайное значение (либо 1, либо 3).

Всякий раз, когда я кладу плитку (1 или 3), я также кладу соответствующую половину соответственно соседнему пространству сетки. Скажем, я поставил 1 на (i,j), затем поставил 2 на (i,j+1).

StoneMatrix = int[8][8];

for (int i = 0; i < StoneMatrix.length; i++) {
    for (int j = 0; j < StoneMatrix.length; j++) {
        if (StoneMatrix[i][j] != 0){
            //field already set as a tile
            continue;
        }

        if (i == StoneMatrix.length - 1) {
            //bottom row
            StoneMatrix[i][j] = 1;
            StoneMatrix[i][j + 1] = 2;
            continue;
        }

        if (j == StoneMatrix.length - 1) {
            //right edge
            StoneMatrix[i][j] = 3;
            StoneMatrix[i + 1][j] = 4;
            continue;
        }

        if (StoneMatrix[i][j + 1] != 0) {
            //field to the right taken.
            StoneMatrix[i][j] = 3;
            StoneMatrix[i + 1][j] = 4;
            continue;
        }

        StoneMatrix[i][j] = putOneOrThreeRandomly();
        putCorrespondingAdjacentTile();
    }
}

Я чувствую, что должен быть простой или более простой способ создания такой мозаики, но я пока не смог его найти. То, что я ищу, это либо какой-то источник, где описан такой алгоритм генерации, либо простое решение, которое исправляет мою ошибку.


person N. Ecker    schedule 25.04.2019    source источник


Ответы (2)


Оптимальная мозаика домино

Создайте случайную максимальную плитку любой шахматной доски размером n на m с 2x1 доминошками. Когда n*m четное, мозаика будет идеальной.

Теория

Рассмотрим белые и черные клетки шахматной доски. Домино должно покрывать как белую, так и черную клетку. Следовательно, если существует некоторая идеальная мозаика, то решение можно преобразовать в граф следующим образом: каждая шахматная клетка становится вершиной, и если костяшка домино покрывает две соседние плитки, две вершины соединяются. Это привело бы к двудольному (все ребра имеют одну белую и одну черную вершину) и (максимально) совпадающему графу.

Следовательно, при наличии сетки любого размера (или любой формы в этом отношении), если мы сможем решить задачу сопоставления максимальной мощности в двудольном графе, мы можем преобразовать решение в мозаику домино.

Реализация (доказательство концепции)

Чтобы решить вышеупомянутую задачу с графом, преобразуйте ее в задачу о максимальном потоке и решите ее вместе с Фордом Фулкерсоном. Соедините узел-источник со всеми белыми плитками, а узел-приемник со всеми черными плитками. Белая плитка указывает на черную плитку, только если они являются соседями в шахматной сетке. Решите со всеми ребрами, имеющими емкость один. Используемые ребра между узлами указывают на то, что там будет размещена костяшка домино.

Пример

Рассмотрим шахматную доску глубиной 2 ряда и шириной 4 столбца. Белые квадраты — это {0, 1, 2, 3}, а черные квадраты — это {4, 5, 6, 7}.

+---+---+---+---+
| 0 | 4 | 1 | 5 |
+---+---+---+---+
| 6 | 2 | 7 | 3 |
+---+---+---+---+

Теперь предположим, что у нас есть два дополнительных узла: 8 источник и 9 приемник. Затем график для определения максимального расхода становится следующим. Обратите внимание, что все ребра имеют пропускную способность 1.

0: 4, 6
1: 4, 5, 7
2: 4, 6, 7
3: 5, 7
4: 9
5: 9
6: 9
7: 9
8: 0, 1, 2, 3

После запуска Ford-fulkerson (с рандомизированным поиском в глубину для интересных решений — используйте BFS, если вы каждый раз хотите получить скучное построчное решение), мы можем обнаружить, что используются следующие ребра. Обратите внимание, что ребра, включающие узлы источника/приемника, были опущены, поскольку они бесполезны для реконструкции листов.

0-4
2-6
1-7
3-5

Наконец, это соответствует следующему замощению

+-----+---+---+
| 0 4 | 1 | 5 |
+-----+   |   |
| 6 2 | 7 | 3 |
+-----+---+---+

Я также создал доказательство концепции на Java здесь: https://github.com/forsythe/domino_tiling. Если вы хотите увидеть это в действии, вот вывод 16x16:

образец вывода 16x16, сгенерированный описанным ниже методом

person nnnte    schedule 31.12.2020

Я «решил» проблему, установив для логического значения значение true, каждый раз, когда я попадаю в состояние, когда вы больше не можете правильно заполнять сетку.

Затем в конце метода генерации, если логическое значение ложно, сетка действительна, или если логическое значение истинно, я перезапускаю метод. В основном грязный "проб и ошибок", я думаю.

Это не то решение, которое я хотел, но оно работает. Поэтому я оставляю этот вопрос открытым.

person N. Ecker    schedule 02.05.2019