ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

动态规划习题

2021-09-03 16:05:26  阅读:161  来源: 互联网

标签:nums max 子结构 cost len 习题 动态 规划 最优


动态规划三要素:

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

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

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

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

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

 

爬楼梯

'''
假设你正在爬楼梯。需要 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))

 

 

 

参考资料:

标签:nums,max,子结构,cost,len,习题,动态,规划,最优
来源: https://www.cnblogs.com/yanshw/p/15223480.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有