我一直在尝试从HackerRank的动态编程部分解决this问题。我阅读了编辑解决方案并理解它。但是,它直接跳到动态编程方法。我想知道蛮力对这个问题的处理方式是什么。
说明:您和您的朋友决定使用由N块组成的堆栈来玩游戏。在这个游戏中,您可以从顶部移除1,2或3块砖块,并将删除的砖块上蚀刻的数字添加到您的分数中。你必须玩,以便获得最大可能的分数。假设您的朋友也会以最佳方式进行游戏并且您迈出第一步。
我最初的想法是列举所有可能的1,2,3长度组合砖,从堆栈顶部到底部。让我们称之为枚举S.然后,找到S中所有x(你的分数)和y(对手的分数)的所有可能(x,y),其中x!= y。最后迭代,通过所有这些对并计算你的最大分数(例如x的最大总和)。
答案 0 :(得分:3)
嗯,这里动态编程只是一种避免多次计算相同子问题的方法(其他可能是使用memoization)。
解决这些问题的一般想法如下:
让A
和B
成为玩家,A
先移动。此外,让f(n,p)
表示玩家p
的最大分数,其大小为n
,即p
大小为n
的堆栈。
这个想法很简单,A
想要最大化f(n,A)
。请注意,输入中给出的初始位置A
最多可以进行3次不同的移动:
此外,如果A
得分为X
,则B
得分为S(n) - X
,其中S(n)
为n
底砖得分的总和。
基于这些观察,我们可以写出:
f(n,A) = max(S(n)-f(n-1,B), S(n)-f(n-2,B), S(n)-f(n-3,B))
。
换句话说,他的最佳结果是从这些可用的移动中获得最大值(请注意,如果叠加很小,可能会少于3次移动)。
现在,动态编程只是用来避免多次计算f(n,p)
的相同值 - 如果扩展f(n,A)
的公式,你会发现它们可以在那里出现的次数越来越多n
增长。因此,为了优化解决方案,已计算的f
值存储在存储器中,并在需要时以恒定时间返回。
答案 1 :(得分:1)
看看Minimax algorithm。你通常建立一个完整的树,其中一个级别将产生你所有可能的移动,下一个级别将为你的对手在前一级别生成的每个状态产生所有可能的移动并继续。在每个级别中,您必须最大限度地减少下一级最坏情况的可能损失。在这里生成所有可能的移动/分支,因此它非常暴力。
显然你可以在Minimax树上修剪,但你应该先看看暴力方法。