我参加了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:
不是this问题的重复项,因为那个人不使用DP;请检查那些重复快乐的手指。
我已表现出足够的努力,没有要求任何人做我的作业。我已经有了自己的解决方案。我感兴趣的是学习一种更好的解决问题的方法(如果存在的话)。
谢谢!
答案 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为a
和dp[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