Скорая Компьютерная Помощь г. Калуга

Полный спектр компьютерных услуг!

Здравствуйте, гость ( Вход | Регистрация )

> Внимание!

  • Вся информация, расположенная в данном и других разделах форума получена из открытых источников (интернет-ресурсы, средства массовой информации, печатные издания и т.п.) и/или добавлена самими пользователями. Администрация форума предоставляет его участникам площадку для общения / размещения файлов / статей и т.п. и не несет ответственности за содержание сообщений, а также за возможное нарушение авторских, смежных и каких-либо иных прав, которое может повлечь за собой информация, содержащаяся в сообщениях.
Ремонт компьютеров в калуге Рекламное место сдается
 
Ответить в эту темуОткрыть новую тему
> Алгоритмы / [Из песочницы] Японские кроссворды и алгоритмы их решения
Decker
сообщение 10.11.2011, 13:17
Сообщение #1


Администратор
*****

Группа: Главные администраторы
Сообщений: 14349
Регистрация: 12.10.2007
Из: Twilight Zone
Пользователь №: 1







Недавно мне выпала следующая задача: написать программу, находящую все решения или их отсутствие для данного японского кроссворда размера NxM. Далее представлены 4 алгоритма решения японских кроссвордов.



Для тех кто не знает что такое японский кроссворд- ссылка на википедию.



Японский кроссворд представляется в памяти в виде двух матриц. Первая размера NxM хранит поле. Закрашенная клетка обозначается 1(один), незакрашенная 0(ноль), неизвестная -1(минус один).

Вторая хранит N кодов строк и M кодов столбцов, заканчивающихся нулем.



Первый алгоритм.

Первым, что я написал, был алгоритм перебора. Поле NxM заполняется 1 и 0. И для каждой строки и каждого столбца проверяется соответствие коду.

Несложно посчитать количество вариантов такого заполнения. Их ровно 2^(N*M). Сложность алгоритма O(2^(N*M)).

Работает достаточно быстро лишь на маленьких кроссвордах (размера не более 15x15).



Второй алгоритм.

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

Очевидно, самый худший вариант- когда все коды строк равны «1, 0» (тоесть 1 блок из 1 клетки). Количество вариантов размещения таких блоков равно M^N. Сложность алгоритма O(M^N).



Следующие алгоритмы уже не являются алгоритмами перебора, но существуют кроссворды которые невозможно решить не используя перебор и кроссворды с огромным количеством решений (например кроссворд NxN, каждая строка и каждый столбец которого состоит из 1 блока единичной длины, имеет N! решений). В конце концов для каждого из таких кроссвордов приходится запускать перебор.



Третий алгоритм.

Третий алгоритм я нашел на следующем сайте. Исходники на паскале так же можно найти на этом же сайте.

Суть алгоритма:

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



Четвертый алгоритм.

Четвертый алгоритм основан на использовании конечных автоматов. Если есть желание, можно прочитать что это такое на википедии. Но большого смысла я в этом не вижу, так как принцип работы конечного автомата и так будет понятен.



Можно считать, без ограничения общности, что мы работаем со строкой и ее кодом.



s — строка.

size2 — длина строки.

size1 — длина схемы автомата.



1) Первый шаг алгоритма- построение схемы автомата.

Пример схемы автомата для кода «4,1»:



(-1,1,1,1,1,0,-1,1,-1),

Где

-1 это произвольное количество незакрашенных клеток (Может быть и 0 незакрашенных клеток),

1 это одна закрашенная клетка,

0 это одна незакрашенная клетка.



2) Второй шаг- попытка принять строку автоматом.

— Создание массива размера size1x(size2+1).

— Заполнение первого столбца массива схемой конечного автомата.

— Остальные элементы массива заполняются -1.

— Заполнение массива.



Функция, заполняющая массив.1.cpp



Пример заполнения массива для строки (-1,-1,-1,1,-1,-1,-1,-1,0,-1) и схемы автомата для кода «4,1» (-1,1,1,1,1,0,-1,1,-1).







Массив заполняется диагональными путями. Каждый путь соответствует одному из расположений блоков «4» и «2» в строке. Например путь, выделенный на картинке, соответствует строке (0,1,1,1,1,0,0,0,0,1)/



3) Третий шаг- извлечение информации из полученного на 2 шаге массива.

— Если в i столбце кроме -1 содержаться 1,0 то клетка s[i-1] может быть и закрашенной и незакрашенной.

— Если в i столбце кроме -1 содержаться только 1 то клетка s[i-1] может быть только закрашенной.

— Если в i столбце кроме -1 содержаться только 0 то клетка s[i-1] может быть только незакрашенной.



В предыдущем примере заполнения массива информация извлекается только из 5 и 10 столбца. Клетка s[4]=1 и s[9]=0, что и так было известно.



Рабочая версия программы: Japan.rar

Original source: habrahabr.ru (comments, light).

Читать дальше


--------------------

Вернуться в начало страницы
 
+Ответить с цитированием данного сообщения

Ответить в эту темуОткрыть новую тему
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 

Рекламное место сдается Рекламное место сдается
Текстовая версия Сейчас: 15.5.2025, 21:05
Рейтинг@Mail.ru
Яндекс.Метрика Яндекс цитирования