Python之动态规划

2023-11-20

序言

最近在学习python语言,语言有通用性,此文记录复习动态规划并练习python语言。

动态规划(Dynamic Programming)

动态规划是运筹学的一个分支,是求解决策过程最优化的过程。20世纪50年代初,美国数学家贝尔曼(R.Bellman)等人在研究多阶段决策过程的优化问题时,提出了著名的最优化原理,从而创立了动态规划。动态规划的应用极其广泛,包括工程技术、经济、工业生产、军事以及自动化控制等领域,并在背包问题、生产经营问题、资金管理问题、资源分配问题、最短路径问题和复杂系统可靠性问题等中取得了显著的效果。

基本思想:将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。

斐波那契数列(Fibonacci sequence)

斐波那契数列,又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称“兔子数列”,其数值为:1、1、2、3、5、8、13、21、34……在数学上,这一数列以如下递推的方法定义:F(0)=1,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)。

先以斐波那契数列为例,了解动态规划。

def fibonacci(num):
    if num == 0:
        return 1
    if num == 1:
        return 1
    return fibonacci(num - 1) + fibonacci(num - 2)


if __name__ == "__main__":
    print(fibonacci(10))

在这里插入图片描述
上述是以递归的方式实现的,然而递归方式存在以下几个缺点:

  • 1)递归调用,占用空间大;
  • 2)递归太深,容易发生栈溢出;
  • 3)可能存在大量重复计算;
结果 (n-1)项 (n-2)项
f(n) f(n-1) f(n-2)
f(5) f(4) f(3)
f(4) f(3) f(2)
f(3) f(2) f(1)
f(2) f(1) f(0)

以上述表格为例,可以看到在求下一个递归结果时,计算了之前已经计算出来的结果,存在重复计算项。

如果采用动态规划的方式,那么可以节省计算,采用数组暂存之前已经计算出来的结果。如下,

def fibonacci_dp(num):
    # 定义一个数组暂存dp结果,数组初始值为-1
    dp = [-1] * (num + 1)
    dp[0] = 1
    dp[1] = 1
    for i in range(2, num + 1):
        dp[i] = dp[i - 1] + dp[i - 2]
    return dp[num]


if __name__ == "__main__":
    print(fibonacci_dp(10))

在这里插入图片描述

不同路径

上面的斐波那契数列是一维数组,较为简单,下面以二维数组为例。

题目描述

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。

问总共有多少条不同的路径?在这里插入图片描述

示例1: 输入:m = 3, n = 7 输出:28

示例2: 输入:m = 3, n = 2 输出:3
解释: 从左上角开始,总共有 3 条路径可以到达右下角。
1.向右 -> 向下 -> 向下
2.向下 -> 向下 -> 向右
3.向下 -> 向右 -> 向下
示例3:
输入:m = 7, n = 3 输出:28
示例4:
输入:m = 3, n = 3 输出:6
1 <= m, n <= 100
题目数据保证答案小于等于 2 * 10^9

python代码

class UniquePaths(object):
    def uniquePaths(self, m: int, n: int) -> int:
        """
        :type m: int
        :type n: int
        :rtype: int
        """

        # 初始化一个二维数组
        dp = [[0] * n for _ in range(m)]
        for i in range(m):
            dp[i][0] = 1
        for j in range(n):
            dp[0][j] = 1
        for i in range(1, m):
            for j in range(1, n):
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
        return dp[m - 1][n - 1]


if __name__ == "__main__":
    demo = UniquePaths()
    print(demo.uniquePaths(7, 3))

在这里插入图片描述

最小路径和

题目描述

给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

说明:一个机器人每次只能向下或者向右移动一步。

在这里插入图片描述

示例1:
输入:grid = [[1,3,1],[1,5,1],[4,2,1]]
输出:7
解释:因为路径 1→3→1→1→1 的总和最小。
示例2:
输入:grid = [[1,2,3],[4,5,6]]
输出:12
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 200
0 <= grid[i][j] <= 100

python代码

class MinPathSum(object):
    def minPathSum(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        row = len(grid)
        column = len(grid[0])
        # 定义dp[i][j]为到(i,j)处的最小路径和
        dp = [[0] * column for _ in range(row)]
        dp[0][0] = grid[0][0]
        # 第0行j列
        for j in range(1, column):
            dp[0][j] = dp[0][j - 1] + grid[0][j]
        # 第i行0列
        for i in range(1, row):
            dp[i][0] = dp[i - 1][0] + grid[i][0]
        # 非第0行或第0列
        for i in range(1, row):
            for j in range(1, column):
                dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j]
        return dp[row - 1][column - 1]


if __name__ == "__main__":
    demo = MinPathSum()
    grid = [[1, 3, 1], [1, 5, 1], [4, 2, 1]]
    print(demo.minPathSum(grid))

在这里插入图片描述

零钱兑换

题目描述

给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。

计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。

你可以认为每种硬币的数量是无限的。

示例 1:
输入:coins = [1, 2, 5], amount = 11
输出:3
解释:11 = 5 + 5 + 1
示例 2:
输入:coins = [2], amount = 3
输出:-1
示例 3:
输入:coins = [1], amount = 0
输出:0
提示:
1 <= coins.length <= 12
1 <= coins[i] <= 231 - 1
0 <= amount <= 104

python代码

class CoinChange(object):
    def coinChange(self, coins: list[int], amount: int) -> int:
        """
        :type coins: List[int]
        :type amount: int
        :rtype: int
        """

        # 状态转移方程dp(i) = min(dp(i-Cj)) + 1,Cj为货币面值
        """
        i<0  忽略
        i==0 dp[0] = 0
        i==1 dp[1] = min(dp[1-1], dp[1-2], dp[1-5]) + 1 = 1
        i==2 dp[2] = min(dp[2-1], dp[2-2], dp[2-5]) + 1 = 1
        i==3 dp[3] = min(dp[3-1], dp[3-2], dp[3-5]) + 1 = 2
        i==4 dp[4] = min(dp[4-1], dp[4-2], dp[4-5]) + 1 = 2
        ... ...
        """
        dp = [0] * (amount + 1)
        dp[0] = 0
        for i in range(1, amount + 1):
            mini = int(1e9)
            for coin in coins:
                if i >= coin:
                    res = dp[i - coin]
                    if 0 <= res < mini:
                        mini = res
            dp[i] = mini + 1 if mini < int(1e9) else -1
        if amount < 1:
            return 0
        return dp[amount]


if __name__ == "__main__":
    demo = CoinChange()
    coins = [1, 2, 5]
    amount = 11
    print(demo.coinChange(coins, amount))

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python之动态规划 的相关文章

随机推荐

  • vue项目打包后如何本都部署访问

    npm run build生成dist项目后 在windows部署访问 方式一 1 新建一个文件夹 进入目录后打开cmd 输入npm init y 2 输入 npm i express s 是用于在 Node js 项目中安装 Expres
  • 小程序实现微信登录Java后端(一)--前端实现

    目录 一 概述 二 登录流程 三 前端代码 四 解读前端代码 1 登录部分 2 检查当前用户是否已登录 3 小程序启动时校验登录 五 阶段性小结 一 概述 最近终于有时间去搞一下准备参加比赛的小程序 小程序一开始设计的是使用邮箱登录 老师建
  • 剑指offer——输出数组中k个最小值(快速,冒泡,选择,插入)

    找k个最小值 基本思路是对数组排序 输出前k个或者后k个 我们回顾一下之前的学习过的集中排序方法 快速排序 class Solution def GetLeastNumbers Solution self tinput k def quic
  • rust房屋建造蓝图_妄想山海房子建造攻略

    妄想山海这个游戏的一大特色就是玩家可以在游戏里建造属于自己的房屋 而且这个房屋可不是几个图或是简单的3d模型 而是一个完整的房屋呦 玩家可以创作或是收集来的房屋设计图 真实打造 所以在妄想山海里房子的建造还是要花点功夫的 下面讯喵喵就为大家
  • Redis 分布式缓存

    分布式缓存 单点 Redis 的问题及解决 数据丢失 实现Redis数据持久化 并发能力 搭建主从集群 实现读写分离 存储能力 搭建分片集群 利用插槽机制实现动态扩容 故障恢复能力 利用哨兵机制 实现健康检测和自动恢复 RDB RDB全称R
  • 利用接口请求获取文件

    1 背景 测试阶段文件上传服务器为测试文件服务器 预览时根据id获取的测试服务器文件 但发到线上后发现文件上传到了测试服务器 读取文件时又是从线上的文件服务器读取的 因此导致了文件显示异常 2 数据恢复分析 先从测试环境获取到文件 这些文件
  • 微信小程序图片使用filter将彩色图片变成黑白以后,border-radius失效的解决办法

    使用css的filter将彩色图片亮度降低之后 设置的border radius会出现失效不起作用的情况 需求 用户在线头像为原始的彩色图片 离线将用户头像改为黑白色 原来的写法
  • 【数据结构】并查集

    文章目录 1 并查集原理 2 并查集的实现 2 1并查集框架 2 2insert 插入元素接口 2 3Findroot查找所属集合 2 4合并两个集合 2 5统计集合个数 3 测试 4 并查集OJ 4 1省份的数量 4 2等式方程的可满足性
  • Enterprise Architect 中文经典教程

    本文使用到的EA工程文件下载 一 Enterprise Architect简介 Enterprise Architect是一个对于软件系统开发有着极好支持的CASE软件 Computer Aided Software Engineering
  • python从键盘上输入一个字符、当输入的是英文字母时_从键盘输入一个字符 若该字符是英文字母是则输入对应的ASCII码...

    展开全部 ascill字母表 a z 97 122 A Z 65 90 0 9 48 57 代码如下 可以循环判断是字母的ascil 输入636f707962616964757a686964616f313333376261340退出 inc
  • 验证微信号的正则表达式

    var wxreg a zA Z 1 a zA Z0 9 5 19
  • vue项目使用视频播放器vue-video-player

    安装使用 插件有版本限制 如果项目使用的是vue2 0版本 请选择安装 4 x版本 否则会安装不成功 yarn add vue video palyer save 或者 npm install vue video palyer save 组
  • python里出现breakoutsideloop_Python ast.Break方法代码示例

    本文整理汇总了Python中ast Break方法的典型用法代码示例 如果您正苦于以下问题 Python ast Break方法的具体用法 Python ast Break怎么用 Python ast Break使用的例子 那么恭喜您 这里
  • Java对JSON路径解析JsonPath例子

    1 jsonpath的特点 不需要定义java bean 不用对多层map多次迭代 就可以获得json解析树中深层次的节点 Jayway的jsonpath解析需要把要解析的json一次加载进内存 2 1 jsonpath表达式的两种方式 t
  • html创建添加地图(超简单)

    1 打开百度地图创建平台 百度地图创建平台 2 根据个人需求改就行了 可加标注 3 点击获取代码 复制下来就可以用了 4 个人用的是HBulider 复制到里面可直接用了 如果有文字显示问题 把编码改成utf 8就行了 5 地图控件位置在网
  • Unity3d + NGUI 的多分辨率适配

    移动端的多机型适配 现在要介绍的是 锁链战记 这款游戏的适配方法 这种适配方法是UI是一个基础尺寸 背景是一个基础尺寸 背景比UI多出的部分是一些没有实际作用的部分 这样的适配方式避免了在iPhone5这样的小屏幕上镶边 首先设定UIRoo
  • matlab函数式里虚数i怎么表示,matlab虚数_matlab 中复数如何表示?

    matlab 中复数如何表示 你i是不是已经被定义为变量了 正常i就是复数单位 可以这样表示的 matlab是否可以定义虚数 想来想去只想到一个比较笨的办法 不过不用if find和循环语句 而且确实管用 a 1 2 3 3i 2i 1i
  • 在任何地方使用Active Directory映像

    介绍 Introduction Active Directory has a neat feature that enables you to upload user images Unfortunately not all systems
  • 算术转换之寻常算术转换

    算术转换之寻常算术转换 题目 include
  • Python之动态规划

    序言 最近在学习python语言 语言有通用性 此文记录复习动态规划并练习python语言 动态规划 Dynamic Programming 动态规划是运筹学的一个分支 是求解决策过程最优化的过程 20世纪50年代初 美国数学家贝尔曼 R