最后剩余数字(动态编程)

时间:2018-01-21 19:19:49

标签: algorithm dynamic-programming game-theory

存在具有N整数(N <5×10 ^ 5)的数组,并且有两个玩家(A和B)顺序地删除该数组的元素。 A试图让最后一个数字变大,B试图缩小。

*两位玩家都可以删除第一个元素或最后一个元素。 * A首先开始删除。

让我们说; A = [3,100,4,50]

-A将删除50,因为如果A删除3则B可以删除100不是A想要的东西。

我通过使用动态编程解决了这个问题,但问题是内存。我使用2D整数数组进行记忆,当我收到一个大小为10 ^ 5的数组时,它消耗了大量的内存(对于这种情况,10 ^ 5x10 ^ 5x2 = 2x10 ^ 10字节,这是18.6千兆字节。)但我想要用最多512 MB的内存来解决这个问题。我的问题是“解决这个问题的空间效率更高的方法是什么?”。

3 个答案:

答案 0 :(得分:4)

假设您计算所有长度k阵列的最佳得分(k将从1开始并逐渐增加)并且同时选择第一个玩家。

您可以从长度为k的阵列计算所有长度k + 1阵列的最佳分数(通过考虑删除第一个或最后一个元素并选择最佳元素)。

因此,您只需保留此数组的两个副本(k和k + 1)并丢弃所有较小的长度即可使用O(N)内存执行此操作。

换句话说,如果将结果存储在大小为[2] [N]的二维数组中,则可以将长度k数组的结果存储在位置k%2(将为0或1)中。< / p>

答案 1 :(得分:4)

实际上,我认为你不需要动态编程。答案将始终是中间的元素,如果 N 是偶数,则答案是两个中间元素中的最大值。以下是证据:

假设您是 A 的玩家,并且您希望剩余的元素大于中间元素。如果元素位于数组的右半部分,您肯定会从数组的开头开始获取元素(尽可能长时间保留您想要的元素)。现在想想玩家 B 会如何反应,为什么他会帮助你实现目标?!当然玩家 B 将开始从数组末尾获取元素以摆脱你想要的大元素。

如果你是玩家 B ,并且你试图保持一个小于中间元素的元素,播放器 A 将开始从另一边去除你想要的小元素。

如果大小元素都在数组的同一侧,则两个玩家都可以计算出他们是否可以拥有他们想要的元素。如果他们中的一个人无法得到他想要的元素,他会推动另一个玩家保持中间元素,因为总是移除另一边的元素。

唯一特殊情况是 N 是偶数,在这种情况下,最后一步将由玩家 A 完成,数组将 2 < / strong>剩下的元素(中间的两个元素)。在这种情况下,玩家 A 肯定会移除较小的元素并保留较大的元素。

答案 2 :(得分:1)

这让我想起了alpha-beta修剪(https://en.wikipedia.org/wiki/Alpha%E2%80%93beta_pruning)。 A / B修剪适用于你有两个玩家竞争游戏的情况你可以为游戏的每个动作分配一个分数,例如国际象棋或西洋跳棋,但这应该同样有效。

问题可归结为树搜索可能的游戏状态和分数,在这种情况下,每个州的玩家之间的差异分数。根据对方玩家的预期得分,A / B修剪允许缩小搜索空间,切断整个子树。这个想法是,不需要考虑导致对方球员得分高于你自己预期得分的子树。