Алгоритм кроссворда с заданной сеткой
Прежде чем написать что-нибудь о проблеме, я должен сообщить вам:
- Эта проблема - моя домашняя работа (у меня было около 1 недели, чтобы вернуть рабочую программу)
- Я работал над этой проблемой около недели, каждый день, пытаясь выяснить свое решение.
- Я не прошу полной программы; Мне нужно общее представление об алгоритме
Проблема:
Учитывая: список слов и "сетка", например:
сетка (X означает любую букву):
X X
XXXX
X X
XXXX
словник:
ccaa
baca
baaa
bbbb
Вы должны найти пример "решение" - возможно ли вставить слова из списка слов в заданную сетку? Если есть хотя бы одно решение, напечатайте его (в зависимости от того, что правильно). Если нет - печатать сообщение, то нет возможного решения. Для данного примера существует решение:
b c
baca
b a
baaa
Мне тяжело писать все, что я уже пробовал (потому что английский не мой родной язык, и у меня также много документов с неправильными идеями).
Мой наивный алгоритм работает примерно так:
-
Первое слово требует только правильной длины, поэтому найдите любое (первое?) слово с правильной длиной (я собираюсь использовать данную примерную сетку и список слов, чтобы продемонстрировать, что я думаю):
c X
cXXX
a X
aXXX
-
Для первой общей буквы (на пересечении 2-х слов) найдите любое (первое) слово, которое соответствует сетке (таким образом, имеет надлежащую длину и общую букву в правильном положении). Если таких слов нет, вернитесь к (1) и произнесите другое первое слово. В оригинальном примере нет слова, которое начинается с "c", поэтому мы возвращаемся к (1) и выбираем следующие слова (этот шаг повторяется несколько раз, пока у нас нет "bbbb" для 1-го слова). Теперь мы имеем:
b X
bXXX
b X
bXXX
И мы ищем слово (слова), которое начинается с "b", например:
b X
baca
b X
bXXX
-
Общий процесс: попытайтесь найти пары слов, которые соответствуют заданной сетке. Если таких слов нет, вернитесь к предыдущему шагу и используйте другую комбинацию - если таковой нет - решения нет.
Все вышеизложенное хаотично, я надеюсь, что вы поймете хотя бы описание проблемы. Я написал проект алгоритма, но я не уверен, что это работает и как правильно его кодировать (в моем случае: С++). Более того, есть случаи (даже в примере выше), что нам нужно найти слово, которое зависит от двух или более других слов.
Может быть, я просто не вижу ничего очевидного, может быть, я слишком глуп, возможно... Ну, я действительно пытался решить эту проблему. Я не знаю английского достаточно хорошо, чтобы точно описать, что я думаю об этой проблеме, поэтому я не могу поставить здесь все свои заметки (я попытался описать одну идею, и это было сложно). Верьте или нет, я потратил много долгих часов, пытаясь найти решение, и у меня почти ничего нет.
Если вы можете описать решение или дать подсказку, как решить эту проблему, я бы очень признателен этому.
Ответы
Ответ 1
Проблема corssword NP-Complete, поэтому ваш лучший снимок - это грубая сила: просто попробуйте все возможности и остановитесь, когда есть возможность действительный. Возврат отказа, когда вы исчерпали все возможные решения.
которые доказывают, что эта проблема NP-Complete можно найти в в этой статье, раздел 3.3
Решение грубой силы с использованием backtracking может быть: [псевдо-код]:
solve(words,grid):
if words is empty:
if grid.isValudSol():
return grid
else:
return None
for each word in words:
possibleSol <- grid.fillFirst(word)
ret <- solve(words\{word},possibleSol)
if (ret != None):
return ret
return None
здесь мы предполагаем, что fillFirst()
- это функция, которая заполняет первое пространство, которое еще не было заполнено [сначала может быть фактически любое согласованное упорядочение пустых пространств, но оно должно быть последовательным!), а isValid()
возвращается boolean, указывающий, является ли данная сетка допустимым решением.
Ответ 2
Сегодня утром я написал прогам. Вот несколько более эффективная версия в псевдокоде:
#pseudo-code
solve ( words , grid ) : solve ( words , grid , None )
solve ( words , grid , filledPositions ) :
if words is empty :
if grid is solved :
return grid
else :
raise ( no solution )
for ( current position ) as the first possible word position in grid
that is not of filledPositions :
# note : a word position must have no letters before the word
# 'before the word' means, eg, to the left of a horizontal word
# no letters may be placed over a ' '
# no letters may be placed off the grid
# note : a location may have two 'positions' : one across , one down
for each word in words :
make a copy of grid
try :
fill grid copy, with the current word, at the current position
except ( cannot fill position ) :
break
try :
return solve ( words\{word} , grid copy ,
filledPositions+{current position} )
except ( no solution ) :
break
raise ( no solution )
Вот мой код для подгонки слова по горизонтали в сетке: http://codepad.org/4UXoLcjR
Вот некоторые вещи, которые я использовал в STL:
http://www.cplusplus.com/reference/algorithm/remove_copy/
http://www.cplusplus.com/reference/stl/vector/