如何使用动态编程在Boggle板上找到所有单词?

时间:2018-07-12 05:03:52

标签: java algorithm puzzle trie boggle

我参加了Coursera的Algorithms, Part II课程,其中一项作业是解决Boggle游戏: http://coursera.cs.princeton.edu/algs4/assignments/boggle.html

荣誉代码要求我不要公开发布解决方案,因此,这是基本算法的伪代码。

visit:
  word <- board[i][j]
  start <- dictionary.match(word, start)
  if start is not null
      visited[i][j] <- true
      word <- prefix + word
      if word is longer than min required length 
          words <- words + word

      for (x, y) ∊ adj(i, j)
          if not visited(x, y)
            visit (x, y)

  visited[i][j] <- false

字典是使用Trie实现的。

上面的代码有效,我通过了作业,但是随后我遇到this博客文章,该文章声称使用动态编程可以提供更快的解决方案:

  

事实证明,我们可以使用一种巧妙的动态编程技术来   快速检查一个单词(在这种情况下是从词典中)是否可以   还是从董事会建造的!

     

这是动态编程思想的核心:

     

要在第[i,j]处找到长度为k的单词(结束位置)   木板的位置,必须找到该单词的第k-1个字母   在[i,j]的相邻单元之一中。

     

基本情况为k = 1。

     

在第[i,j]个字符中会找到一个长度为1的字母(结束位置)   单词中唯一字母的董事会单元格与   板的第[i,j]个位置。

     

一旦动态编程表中填充了基本情况,我们   可以在长度为k,k> 1的任何单词的基础上构建。

不幸的是,作者的解释工作很差,我无法遵循他的解决方案。不过,我很想,希望这里有人可以向我解释。

PS:

  1. 不是this问题的重复项,因为那个人不使用DP;请检查那些重复快乐的手指。

  2. 我已表现出足够的努力,没有要求任何人做我的作业。我已经有了自己的解决方案。我感兴趣的是学习一种更好的解决问题的方法(如果存在的话)。

谢谢!

1 个答案:

答案 0 :(得分:2)

DP(错误)解决方案的想法很简单,假设我们要检查表中是否存在“苹果”一词。

  • 让我们创建一个表dp[k][n][n],其中dp[a][x][y]表示长度为a的单词的前缀是否可以在单元格(x, y)处结束。

    [a][p][p]
    [x][x][l]
    [x][x][e]
    

对于上表dp[1][0][0] = true,因为apple的前缀长度1为adp[2][0][1] = true等。

  • 那么,如何检查dp[a][x][y]是否正确?检查(x,y)的所有相邻单元格,如果其相邻单元格中有一个dp[a - 1][][] = true,那么dp[a][x][y]也为true。对于我们的示例,对于单元格(0,2)dp[3][0][2] = true,作为其邻居之一,单元格(0,1)具有dp[2][0][1] = true
  • 默认情况下,所有dp[0][x][y] = true
  • 对于任何单元格(x, y),如果dp[length of word][x][y] = true->表中存在该单词。

请注意,当一个字符被使用超过一次时,此解决方案无法检查情况。

就像我们需要查找单词apa并使用上表一样

dp[1][0][0] = true -> dp[2][0][1] = true -> dp[3][0][0] = true