动态规划之博弈问题

相关题目

486. 预测赢家
877. 石子游戏

这类题目典型的解题框架:

  • 在当前状态下,判断先手的最优策略;
  • 先手的策略选定后,后手的策略随之调整;
  • 循环前两个过程;
class Solution:
	"""
	486. 预测赢家
	https://leetcode.cn/problems/predict-the-winner/description/
	"""
    def PredictTheWinner(self, nums: List[int]) -> bool:
        if not nums:
            return 0
        n = len(nums)
        fmap = [[0] * n for _ in range(n)]
        gmap = [[0] * n for _ in range(n)]
        for i in range(n):
            fmap[i][i] = nums[i]

        for i in range(1, n):
            L, R = 0, i
            while R < n:
                fmap[L][R] = max(nums[L]+gmap[L+1][R], nums[R]+gmap[L][R-1])
                gmap[L][R] = min(fmap[L+1][R], fmap[L][R-1])
                L += 1
                R += 1
        p1_score = fmap[0][n-1]
        p2_score = sum(nums) - p1_score

        return True if p1_score >= p2_score else False


class StoneGame:
    """
    877. 石子游戏
    https://leetcode.cn/problems/stone-game/
    """
    def solution(self, piles: List[int]) -> bool:
        n = len(piles)
        # 定义dp数组,对于piles[i...j]这部分石头堆,
        # 先手能获得的最高分数为 dp[i][j][0]
        # 后手能获得的最高分数为 dp[i][j][1]
        dp = [[[0, 0] for _ in range(n)] for _ in range(n)]

        # base case
        for i in range(n):
            dp[i][i][0] = piles[i]
            dp[i][i][1] = 0

        #  遍历数组,从左往右,从下往上
        for i in range(n-2, -1, -1):
            for j in range(i+1, n):
                # 先手选择左边石头
                left = piles[i] + dp[i+1][j][1]
                # 先手选择右边石头
                right = piles[j] + dp[i][j-1][1]

                # 先手选择更大的结果,后手策略随之调整
                if left > right:
                    dp[i][j][0] = left
                    dp[i][j][1] = dp[i+1][j][0]
                else:
                    dp[i][j][0] = right
                    dp[i][j][1] = dp[i][j-1][0]

        fir = dp[0][n-1][0]
        sec = dp[0][n-1][1]
        return True if fir > sec else False```


你可能感兴趣的:(数据结构与算法,LeetCode,动态规划,算法)