877 石子游戏(记忆型递归、动态规划)
发布日期:2021-05-07 21:56:21 浏览次数:24 分类:精选文章

本文共 1293 字,大约阅读时间需要 4 分钟。

亚历克斯和李用几堆石子做游戏。偶数堆石子排成一行,每堆都有正整数颗石子 piles[i]。游戏以谁手中的石子最多来决出胜负。石子的总数是奇数,所以没有平局。亚历克斯和李轮流进行,亚历克斯先开始。每回合,玩家从行的开始或结束处取走整堆石头。这种情况一直持续到没有更多的石子堆为止,此时手中石子最多的玩家获胜。假设亚历克斯和李都发挥出最佳水平,当亚历克斯赢得比赛时返回 true,当李赢得比赛时返回 false。

动态规划解法

为了解决这个问题,我们可以使用动态规划的方法来找到亚历克斯是否能在最佳策略下赢得比赛。我们将使用一个二维数组 dp,其中 dp[i][j] 表示从第 i 堆到第 j 堆的最大相对分数差。

  • 初始化:首先,我们初始化 dp 表,其中 dp[i][i] 表示只有一个石子堆的情况,此时分数差就是该堆的石子数。

  • 填充 dp 表:我们按区间长度从小到大逐步填充 dp 表。对于每个区间长度 j - i + 1,计算从 i 到 j 的最大相对分数差。我们考虑两种情况:取左边的石子堆或取右边的石子堆,并选择较大的那个作为当前区间的最大相对分数差。

  • 最终判断:填充完整个 dp 表后,dp[0][n-1] 就是整个石子堆的最大相对分数差。如果这个值大于 0,说明亚历克斯能赢,否则李赢。

  • 以下是具体的代码实现:

    import sys
    class Solution:
    def stoneGame(self, piles: list) -> bool:
    n = len(piles)
    dp = [[0] * n for _ in range(n)]
    for i in range(n):
    dp[i][i] = piles[i]
    for j in range(1, n):
    for i in range(j - 1, -1, -1):
    dp[i][j] = max(piles[i] - dp[i + 1][j], piles[j] - dp[i][j - 1])
    return dp[0][n - 1] > 0

    代码解释

  • 初始化 dp 表:我们创建一个大小为 n x n 的二维数组 dp,其中 dp[i][i] 初始化为 piles[i]。

  • 填充 dp 表:我们从区间长度 1 开始,逐步增加到 n。对于每个区间长度 j,i 从 j-1 递减到 0。对于每个 i,计算 dp[i][j] 的值:

    • 取左边的石子堆:piles[i] - dp[i+1][j]
    • 取右边的石子堆:piles[j] - dp[i][j-1]
    • dp[i][j] 取这两者的最大值。
  • 返回结果:最终,dp[0][n-1] 表示整个石子堆的最大相对分数差。如果这个值大于 0,返回 true,表示亚历克斯赢;否则返回 false。

  • 这种方法利用动态规划高效地解决了问题,避免了递归的重复计算,时间复杂度为 O(n^2),适用于较大的输入规模。

    上一篇:395 至少有K个重复字符的最长子串(递归)
    下一篇:700 二叉搜索树中的搜索(递归)

    发表评论

    最新留言

    关注你微信了!
    [***.104.42.241]2025年04月16日 17时28分14秒