Leetcode刷题(24) DP Table斜着遍历, 且只用Table的上半三角的动态规划

Leetcode刷题(24) DP Table斜着遍历, 且只用Table的上半三角的动态规划

博弈问题

参考labuladong的动态规划之博弈问题

877. 石子游戏

class Solution(object):
    def stoneGame(self, piles):
        """
        :type piles: List[int]
        :rtype: bool
        """
        n = len(piles)
        dp = [[[0, 0] for _ in range(n)] for i in range(n)]
        for i in range(n):
            dp[i][i][0] = piles[i]
        
        for i in range(n-1):
            for j in range(n-1, i, -1):
                # i, j状态时候先手拿左边的石头
                left = dp[i+1][j][1] + piles[i]
                # i, j状态时候先手拿右边的石头
                right = dp[i][j-1][1] + piles[j]
                
                # 如果先手拿左边的石头导致的剩下阶段的石头多, 就选择左边的并转移状态
                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]
        return dp[0][n-1][0] - dp[0][n-1][1] > 0


参考labuladong的动态规划: 戳气球

暴力回溯穷举并全局搜索最大分数法

class Solution(object):
    def __init__(self):
        self.maxNnm = -float('Inf')

    def maxCoins(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        def backtrack(numbers, score):
            if len(numbers) == 0:
                self.maxNnm = max(self.maxNnm, score)

            n = len(numbers)
            for i in range(n):
                # 记录将要被戳破气球的数字
                tmp = nums[i]

                # 得到将要被戳破的气球相邻两边的气球
                if i - 1 < 0:
                    nums_1 = 1
                else:
                    nums_1 = nums[i-1]
                if i + 1 >= n:
                    nums_2 = 1
                else:
                    nums_2 = nums[i + 1]
                
                # 戳破索引为i的气球
                point = nums_1 * tmp * nums_2
                score += point
                numbers.pop(i)
                backtrack(numbers, score)

                # 将之前被戳破的气球放回原位
                numbers.insert(i, tmp)
                score -= point

        backtrack(nums, 0)
        return self.maxNnm

DP Table, 斜着遍历

class Solution(object):
    def maxCoins(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums)
        dp = [[0] * (n + 2) for _ in range(n + 2)]
        # 在nums的两边加上1, 作为辅助
        nums.insert(0, 1)
        nums.append(1)
        # 遍历状态
        for i in range(n + 1, -1, -1):
            for j in range(i + 1, n + 2):
                # 遍历选择(戳爆(i, j)中的哪一个是这个开区间中最后一个被戳爆的
                for k in range(i + 1, j):
                    # 注意这里是nums[i] * nums[k] * nums[j], 不是nums[k-1] * nums[k] * nums[k+1]
                    dp[i][j] = max(dp[i][j], dp[i][k] + nums[i] * nums[k] * nums[j] + dp[k][j])
        return dp[0][n+1]

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值