【发布时间】:2018-11-13 18:21:38
【问题描述】:
我有一个关于动态编程的任务。 我要设计一个有效的算法来执行以下操作: 有一条小路,布满斑点。用户可以使用一系列按钮向前移动到路径的尽头。有3个按钮。一个让你前进 2 个位置,一个让你前进 3 个位置,一个让你前进 5 个位置。路径上的点不是黑色就是白色,你不能落在黑点上。该算法找到到达终点所需的最少按钮按下次数(超过最后一个点,可以超过它)。 用户输入用于“n”,即点数。并用 n 个 B 或 W(黑色或白色)填充数组。第一个点必须是白色的。这是我到目前为止所拥有的(它只意味着是伪的):
int x = 0
int totalsteps = 0
n = user input
int countAtIndex[n-1] <- Set all values to -1 // I'll do the nitty gritty stuff like this after
int spots[n-1] = user input
pressButton(totalSteps, x) {
if(countAtIndex[x] != -1 AND totalsteps >= countAtIndex[x]) {
FAILED } //Test to see if the value has already been modified (not -1 or not better)
else
if (spots[x] = "B") {
countAtIndex[x] = -2 // Indicator of invalid spot
FAILED }
else if (x >= n-5) { // Reached within 5 of the end, press 5 so take a step and win
GIVE VALUE OF TOTALSTEPS + 1 A SUCCESSFUL SHORTEST OUTPUT
FINISH }
else
countAtIndex[x] = totalsteps
pressButton(totalsteps + 1, x+5) //take 5 steps
pressButton(totalsteps + 1, x+3) //take 3 steps
pressButton(totalsteps + 1, x+2) //take 2 steps
}
我很欣赏这可能看起来很糟糕,但我希望它可以顺利进行,我只是想在我写得更好之前确保理论是合理的。我想知道这是否不是解决这个问题的最有效方法。除此之外,在有大写字母的地方,我不确定如何“失败”程序,或者如何返回“成功”值。 任何帮助将不胜感激。
如果不清楚,我应该添加,我正在使用 countAtIndex[] 来存储到达路径中该索引的移动次数。即在位置 3 (countAtIndex[2]) 的值可能为 1,这意味着它采取了 1 步才能到达那里。
【问题讨论】:
-
你的直觉是对的,你的函数参数是对的。但是,您在实现上遗漏了一点。否则 if (x >= n-5) 将对所有可能的解决方案运行,因此当达到该解决方案时,这不是最佳解决方案(最短)。最佳解决方案是那些总步数最小的解决方案。还不清楚第一部分是如何工作的,因为您没有显示如何更新 countAtIndex[x]。请注意,您可以在不同的步骤(totalsteps)中到达同一个地方(x),因此如果您有兴趣获取稍后使用的路径,则需要使用 countAtIndex[x][totalSteps]
-
您好,感谢您的回答。猜猜我只是想知道我的想法是否合理而不是到处都是。我忘记在最后一个 else 语句中输入 countAtIndex[X] 的更新,但不知道这是否会影响您所说的内容。要重新修改这个。再次感谢:)
-
解决动态规划问题总是有两种方法:自上而下的记忆化,或自下而上系统地填充输出数组。他们的共同点是从 2 个或多个选项中选择最佳答案的递归关系。您的代码中似乎没有这个概念(为
countAtIndex[x]选择最佳值)。附带说明一下,您似乎选择了一种自上而下的递归方法,我的直觉是自下而上的迭代解决方案会减少代码。 -
所以我的问题是:作业是否指定您应该使用记忆实现自上而下的递归解决方案,或者您是否允许选择使用动态编程的任何实现?
-
任何实现都可以,不需要任何细节。 “描述一种有效的算法,该算法确定您为获胜而需要按下的最少按钮数。”除此之外,它还说“提示:使用动态编程”,但这是给定的。
标签: algorithm dynamic pseudocode memoization