• 动态规划习题


    动态规划三要素:

    最优子结构:子问题 会影响 父问题的最优解

      // 注意子问题影响,而不是子问题的解影响,

      // 当然有些问题是子问题的解影响父问题的解,我想说的是不全是解和解得关系,子问题的最优解和父问题的最优解可能毫无关系

    状态转移:根据子问题 如何推出 父问题的解,递推关系式

    边界问题:最小子问题的解是否已知

    爬楼梯

    '''
    假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
    每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
    
    注意:给定 n 是一个正整数。
    
    示例 1:
    输入: 2
    输出: 2
    解释: 有两种方法可以爬到楼顶。
    1.  1 阶 + 1 阶
    2.  2 阶
    
    示例 2:
    输入: 3
    输出: 3
    解释: 有三种方法可以爬到楼顶。
    1.  1 阶 + 1 阶 + 1 阶
    2.  1 阶 + 2 阶
    3.  2 阶 + 1 阶
    
    分析:
    假定n=10,首先考虑最后一步的情况,要么从第九级台阶再走一级到第十级,要么从第八级台阶走两级到第十级,因而,要想到达第十级台阶,最后一步一定是从第八级或者第九级台阶开始.也就是说已知从地面到第八级台阶一共有X种走法,从地面到第九级台阶一共有Y种走法,那么从地面到第十级台阶一共有X+Y种走法.
    即F(10)=F(9)+F(8)
         分析到这里,动态规划的三要素出来了.
            边界:F(1)=1,F(2)=2
            最优子结构:F(10)的最优子结构即F(9)和F(8)
            状态转移函数:F(n)=F(n-1)+F(n-2)
    '''
    
    
    class Solution(object):
        def climbStairs(self, n):
            """
            :type n: int
            :rtype: int
            """
    
            if n<=2:
                return n
            a=1 #边界
            b=2 #边界
            temp=0
            for i in range(3,n+1):
                temp=a+b    #状态转移
                a=b #最优子结构
                b=temp  #最优子结构
            return temp
    
    
    print(Solution().climbStairs(10))

    小偷偷东西

    '''
    一个小偷准备挨家挨户进行偷窃,每一家都有一些能偷到的金额值,但是不能连续进入相邻的两间房屋,否则会被发现。
    将这个设定抽象成一个数组,每家拥有的金额组成一个非负的整型数组,在不被发现的情况下,计算小偷能偷到的最大数额。
    例如[1,2,5,3,4,8,2],那么最大值就是:第一家(1)+第三家(5)+第六家(8)=14.
    
    最优子结构:最后一家偷不偷,偷则加上前两位的最大值,不偷则是前一位的最大值
    边界:d[0]=nums[0], d[1]=max(nums[0], nums[1])
    状态转移函数:d[i]=max(d[i-1], d[i-2]+nums[i])
    '''
    
    
    class Solution(object):
        def rob(self, nums):
            if len(nums)==0:
                return 0
            if len(nums)<=2:
                return max(nums)
            dp = []
            dp.append(nums[0])
            dp.append(max(nums[0], nums[1]))
            for i in range(2, len(nums)):
                dp.append(max(dp[i-1], dp[i-2]+nums[i]))
            return dp[-1]
    
    
    if __name__ == '__main__':
        nums = [1,2,5,3,4,8,2]
        print(Solution().rob(nums))

    最小花费爬楼梯

    '''
    数组的每个下标作为一个阶梯,第 i 个阶梯对应着一个非负数的体力花费值 cost[i](下标从 0 开始)。
    每当你爬上一个阶梯你都要花费对应的体力值,一旦支付了相应的体力值,你就可以选择向上爬一个阶梯或者爬两个阶梯。
    请你找出达到楼层顶部的最低花费。在开始时,你可以选择从下标为 0 或 1 的元素作为初始阶梯。
    
    最优子结构:f(9)和f(8)
    边界:f(0)=1, f(1)=100
    递推式:f(10)=min(f(9)+cost(9), f(8)+cost(8))
    '''
    
    
    class Solution(object):
        def minCostClimbingStairs(self, cost):
            if len(cost) <= 1:
                return min(cost)
            dp = []
            dp.append(cost[0])
            dp.append(cost[1])
            for i in range(2, len(cost)+1):
                if i==len(cost):
                    dp.append(min(dp[i-1], dp[i-2]))
                else:
                    dp.append(min(dp[i-1]+cost[i], dp[i-2]+cost[i]))
            return dp[-1]

    最大和子序列

    这个问题还是挺难的,很多教程并没有 彻彻底底 讲清楚逻辑,我思考了很久才得出下图

    '''
    给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
    
    示例:
    输入: [-2,1,-3,4,-1,2,1,-5,4],
    输出: 6
    解释: 连续子数组 [4,-1,2,1] 的和最大,为 6
    '''
    
    nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
    nums = [-2, -1, -3, 4, -1, 2, 1, -5, 4]
    dp = [-2, 1, -2, 4, 3, 5, 6, 1, 5]
    # nums = [-2, 1, -3]
    # nums = [1, -5, 2]
    
    
    class Solution(object):
        def maxSubArray(self, nums):
            """
            :type nums: List[int]
            :rtype: int
            """
            # 判断边界
            if len(nums) == 0:
                return 0
    
            d = []  # 定义一个表格进行存储上一个子问题的最优解
            d.append(nums[0])  # 第一个最优解为第一个元素
            max_ = nums[0]  # 返回的最大值
            for i in range(1, len(nums)):
                if nums[i] > nums[i] + d[i - 1]:
                    d.append(nums[i])
                else:
                    d.append(nums[i] + d[i - 1])
                print(d)
                if max_ < d[i]:
                    max_ = d[i]
            return max_
    
    
    print(Solution().maxSubArray(nums))

    下面是我一个学生写的,也挺巧妙

    def max_arr(a):
        max_v = 0
        for i in range(1, len(a)):
            if a[i - 1] > 0:
                a[i] += a[i-1]
            max_v = max(max_v, a[i])
        return max_v

    参考资料:

  • 相关阅读:
    面对苹果的抄袭指责,小米到底有没有抄袭?
    如何用Ajax传一个数组数据
    为何日本人如此重视孩子的早餐问题
    常见编程语言对REPL支持情况小结
    坚持未必都是美德,也可能是无知
    PHP 5.4语法改进与弃用特性
    解决CI框架的Disallowed Key Characters错误提示
    如何抓取开了gzip的网页
    CodeIgniter自带的数据库类使用介绍
    Python内部变量与外部变量
  • 原文地址:https://www.cnblogs.com/yanshw/p/15223480.html
Copyright © 2020-2023  润新知