给定网格的填字游戏算法

时间:2011-12-21 04:29:57

标签: algorithm crossword

在我写一些关于这个问题之前,我需要告诉你:

  1. 这个问题是我的作业(我有大约1个星期的时间来恢复工作程序)
  2. 我每天都在研究这个问题大约一个星期,试图找出我自己的解决方案
  3. 我不是要求完整的程序;我需要一个关于算法的一般概念
  4. 问题:

    给出:单词列表和“网格”,例如:

    网格(X表示任何字母):

    X X 
    XXXX
    X X
    XXXX
    

    单词表:

    ccaa
    baca
    baaa
    bbbb
    

    你必须找到示例“解决方案” - 是否可以将wordlist中的单词装入给定的网格?如果至少有一个解决方案,请打印一个(无论哪个正确)。如果没有 - 打印消息,那就没有可能的解决方案。举个例子,有一个解决方案:

    b c 
    baca
    b a 
    baaa
    

    我很难写出我已经尝试过的所有东西(因为英语不是我的母语,我也有很多关于错误的想法的论文)。

    我的天真算法的工作原理如下:

    1. 第一个词需要适当的长度,所以找到正确长度的任何(第一个?)单词(我将使用给定的示例网格和单词列表来演示我的想法):

      c X 
      cXXX
      a X
      aXXX
      
    2. 对于第一个常见的字母(在2个字的交叉处)找到适合网格的任何(第一个)字(因此,具有适当的长度和 common 关于正确位置的信件)。如果没有这样的单词,请返回(1)并取另一个单词。在原始示例中,没有以“c”开头的单词,因此我们返回到(1)并选择下一个单词(此步骤重复几次,直到我们对第一个单词有“bbbb”)。现在我们有:

      b X 
      bXXX
      b X
      bXXX
      

      我们正在寻找一个以“b”开头的单词,例如:

      b X 
      baca
      b X
      bXXX
      
    3. 一般过程:尝试找到适合到给定网格的单词对。如果没有这样的话,请回到上一步并使用另一种组合 - 如果没有这样的话 - 没有解决方案。

    4. 上面的一切都是混乱的,我希望你至少能理解问题的描述。我写了一个算法草案,但我不确定它是否有效以及如何正确编码(在我的例子中:c ++)。此外,有些情况(即使在上面的示例中)我们需要在2个或更多其他单词上找到依赖的单词。

      也许我只是看不到明显的东西,也许我太傻了,也许......好吧,我真的试图解决这个问题。我不太了解英语,无法准确描述我对这个问题的看法,所以我不能把所有的笔记放在这里(我试图描述一个想法而且很难)。信不信由你,我花了很长时间试图找出解决方案,而我几乎什么都没有......

      如果你能描述一个解决方案,或者提示如何解决这个问题,我真的很感激。

2 个答案:

答案 0 :(得分:6)

corssword问题是NP-Complete,所以你的最佳镜头是蛮力:只是尝试所有可能性,并在可能性有效时停止。当你用尽所有可能的解决方案时返回失败。

可以在this article第3.3节

中找到

减少,证明此问题是NP-Complete

使用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()是一个填充第一个空格的函数,该空格尚未填充[首先实际上可以是空格的任何一致排序,但它应该是一致的!],{{1返回一个布尔值,指示给定的网格是否是有效的解决方案。

答案 1 :(得分:3)

今天早上我写了一个程序。这是伪代码中稍微高效的版本:

#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/