考虑一个无聊的白色和红色方块的游戏,顺序如下:
(开始ww w w w w r r w w w w r r r r r w w完成)
w =白色。 r =红色。
有3个按钮。 绿色按钮:移动5步。 黄色按钮:移动3步。 蓝色按钮:移动3步。
游戏规则: -如果玩家落在红场上,则输。 -第一位玩家完成游戏胜利。 -允许在白色正方形上登陆。
贪婪算法:
x = 0
steps = 0
stop = false
while (....)
if a[x+5] is white then
push the green buttton and x= x+5, steps++
if a[x+3] is white then
push the yellow buttton and x= x+3, steps++
if a[x+2] is white then
push the blue buttton and x= x+2, steps++
else stop = true
必填:获胜的最低步骤。
通过遵循上面的贪婪算法,解决方案将为552225,而最佳解决方案为33555。
我的问题是如何应用动态算法找到最佳解决方案?
答案 0 :(得分:0)
您想要做的是产生一个包含最小成本和最佳前举的数组。您将其从头到尾填满,然后从头到尾阅读最佳解决方案。像这样:
min_cost = [infinite for all steps]
arriving_move = [none for all steps]
For each i in 0 to steps-1:
if square[i] = 'r':
pass
else:
for j in 2, 3, 5:
if i <= j:
if min_cost[i-j] + 1 < min_cost[i]:
min_cost[i] = min_cost[i-j] + 1
arriving_move[i] = j
reversed_answer = []
i = steps-1
while arriving_move[i] is not none:
reversed_answer.append(arriving_move[i])
i = i - arriving_move[i]
answer = reversed(reversed_answer)
注意,这将找到一个最佳游戏,您可以直接进入终点。在您的示例中,移动将因此出到33553。
如果您对“超过标记”表示满意,则必须添加一个特殊的末端节点,并在末端添加自己的特殊规则。
答案 1 :(得分:0)
想法:回想一下。假设您在i
中。到达此单元格有哪些选择?
// Assume cell[i] = min number of moves to last cell starting from this cell
cell[n] = 0 //finish cell
cell[0..n-1] = ∞
for i = n to 1
cell[i-1] = min(cell[i-1], cell[i]+1) //if cell[i-1] not red
cell[i-3] = min(cell[i-1], cell[i]+1) //if cell[i-3] not red
cell[i-5] = min(cell[i-1], cell[i]+1) //if cell[i-5] not red
最后,cell[0]
的值显示完成游戏所需的最少步骤。
答案 2 :(得分:0)
要达到终点,您应该先登陆
finish - 5
或finish - 3
或finish - 2
,然后从那里再单击1个按钮以到达finish
。
为此的递归公式:
minSteps(end) = 1 + Math.min( minSteps(end-5), Math.min(minSteps(end-2), minSteps(end-3)) )
您可以像在(Java)中那样编写带有备注的代码:
private static int minSteps( int start, int end, String s ) {
if ( end < start ) return Integer.MAX_VALUE;
if ( end == start ) return 0;
if ( s.charAt(end) == 'r' ) {
dp[end] = Integer.MAX_VALUE;
return dp[end];
}
if ( dp[end] != -1 ) return dp[end];
int stepTwo = minSteps( start, end - 2, s );
int stepThree = minSteps( start, end - 3, s);
int stepFive = minSteps( start, end - 5, s );
int min = Math.min( Math.min( stepTwo, stepThree ), stepFive );
if ( min != Integer.MAX_VALUE ) {
dp[end] = 1 + min;
} else {
dp[end] = min;
}
return dp[end];
}
对于输入w w w w w w r r w w w w r w r w r w
,所得的dp
数组为:
[-1, 2147483647, 1, 1, 2, 1, 2147483647, 2147483647, 2, 3, 2, 3, 2147483647, 3, 2147483647, 3, -1, 4]
,答案为4:18 -> 16 -> 11 -> 6 -> 1
然后,您可以按照dp
数组从头开始建立跳转。