如何改进这种动态编程解决方案?

时间:2013-07-08 05:32:16

标签: algorithm dynamic-programming

原始问题陈述Pile it up

总结:两名玩家A和B玩一个由2堆X和Y币组成的游戏。每回合他都可以做以下其中一项:

  • 从一堆(至少1枚硬币)中移除任意数量的硬币
  • 从两个桩中取出相同数量的硬币
  • 转弯。这仍然算作一个回合。

当无法移动并且无法移动的玩家输掉时,游戏结束。两位球员都发挥出色。两位玩家在游戏开始前计算游戏结果。失败的玩家试图最大化游戏中的回合次数和获胜的玩家试图最小化转弯。没有玩家可以超过P次。 A开始游戏。输出获胜者的名字和游戏中由单个空格分隔的移动数。 0 <= X,Y,P <= 1000

我提出了一个O(n ^ 3)DP解决方案,但考虑到这个问题,这肯定不足以解决这个问题。如果轮到你玩,那么d [i,j]是获胜的最小转弯次数,并且分别在桩X和Y中留下i和j币。然后我们有:

d[i, j] = 0 if i = j = 0
          1 if (i = 0 && j > 0) or (i > 0 && j = 0) or (i = j && i > 0)
          min(min(d[i-p, j]), min(d[i, j-q), min(i-r, j-r)) if a each substate is a losing position
          max of all winning position substate if no losing substate is found

最后,d[i,j] = d[i,j] + 2*P if [i,j]是一个获胜状态,你不会立即从一开始就获胜。

从上面的表述中可以看出,这是一个O(n ^ 3)解决方案。我想改进我对O(n ^ 2)的解决方案,我该如何重新解决这个问题呢?

1 个答案:

答案 0 :(得分:1)

首先获胜的职位是

  1. 1空桩
  2. 两堆相同数量的硬币
  3. 球员什么时候轮到他? 假设位置是(3,2),那么对他来说是3个选项。

    1. 他可以移动到(2,2)但这使得它成为对手的胜利位置。
    2. 他可以移动到(1,0),但这又是对手的胜利位置。
    3. 如果他选择跳过转弯,那么对手也可以跳过转弯。这次跳过最多可以进行P转。
    4. 取决于P的奇偶校验(无论P是偶数还是奇数)并且取决于谁开始跳过序列,我们可以找到获胜的人。找到转弯的数量并不是那么难。

      为什么跳过序列最佳?
      好吧,如果你输了,你会想要在游戏中停留更长时间。(正如游戏规则中所说的那样。)所以即使我知道基于P的平价,我将失去,我可以通过P转有意义吗?
      我鼓励您使用这种洞察力来提高算法速度,但如果您在实施算法时遇到问题,请提出问题!