动态规划 (Dynamic Programming) 算法概念-Python示例

动态规划算法Dynamic Programming 一、 二、 三、 参考文献 阅读详情

Python 实例详解

1. 斐波那契数列
# 传统递归方法 - 效率低下 O(2^n)
def fibonacci_recursive(n):
    if n <= 1:
        return n
    return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2)

# 动态规划方法 - 时间复杂度 O(n),空间复杂度 O(n)
def fibonacci_dp(n):
    if n <= 1:
        return n
    
    # 创建状态数组
    dp = [0] * (n + 1)
    dp[0] = 0
    dp[1] = 1
    
    # 状态转移
    for i in range(2, n + 1):
        dp[i] = dp[i - 1] + dp[i - 2]
    
    return dp[n]

# 空间优化版本 - 空间复杂度 O(1)
def fibonacci_optimized(n):
    if n <= 1:
        return n
    
    prev2, prev1 = 0, 1
    
    for i in range(2, n + 1):
        current = prev1 + prev2
        prev2, prev1 = prev1, current
    
    return prev1
2. 硬币找零问题
# 找到组成金额所需的最少硬币数
def coin_change(coins, amount):
    # dp[i] 表示组成金额 i 所需的最少硬币数
    dp = [float('inf')] * (amount + 1)
    dp[0] = 0  # 组成金额0需要0个硬币
    
    # 对于每个金额
    for i in range(1, amount + 1):
        # 尝试每种硬币
        for coin in coins:
            if coin <= i:
                # 状态转移方程
                dp[i] = min(dp[i], dp[i - coin] + 1)
    
    return dp[amount] if dp[amount] != float('inf') else -1

# 示例使用
print(coin_change([1, 3, 4], 6))  # 输出: 2 (3+3)
3. 编辑距离问题
# 计算两个字符串之间的最小编辑距离
def min_distance(word1, word2):
    m, n = len(word1), len(word2)
    
    # dp[i][j] 表示 word1[0...i-1] 转换为 word2[0...j-1] 的最小操作数
    dp = [[0] * (n + 1) for _ in range(m + 1)]
    
    # 初始化边界条件
    for i in range(m + 1):
        dp[i][0] = i
    for j in range(n + 1):
        dp[0][j] = j
    
    # 状态转移
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if word1[i - 1] == word2[j - 1]:
                # 字符相同,无需操作
                dp[i][j] = dp[i - 1][j - 1]
            else:
                # 取三种操作的最小值
                dp[i][j] = min(
                    dp[i - 1][j] + 1,     # 删除
                    dp[i][j - 1] + 1,     # 插入
                    dp[i - 1][j - 1] + 1  # 替换
                )
    
    return dp[m][n]
4. 最长递增子序列
# 找到数组中最长递增子序列的长度
def length_of_lis(nums):
    if not nums:
        return 0
    
    # dp[i] 表示以 nums[i] 结尾的最长递增子序列长度
    dp = [1] * len(nums)
    
    for i in range(1, len(nums)):
        for j in range(i):
            if nums[j] < nums[i]:
                dp[i] = max(dp[i], dp[j] + 1)
    
    return max(dp)

# 优化版本 - 使用二分查找 O(n log n)
def length_of_lis_optimized(nums):
    import bisect
    
    tails = []
    
    for num in nums:
        # 二分查找插入位置
        pos = bisect.bisect_left(tails, num)
        
        if pos == len(tails):
            tails.append(num)
        else:
            tails[pos] = num
    
    return len(tails)
5. 背包问题
# 0-1背包问题:在限定重量下获取最大价值
def knapsack(weights, values, capacity):
    n = len(weights)
    
    # dp[i][w] 表示前i个物品在容量为w时的最大价值
    dp = [[0] * (capacity + 1) for _ in range(n + 1)]
    
    # 状态转移方程
    for i in range(1, n + 1):
        for w in range(capacity + 1):
            # 不选择第i个物品
            dp[i][w] = dp[i - 1][w]
            
            # 如果能选择第i个物品,比较选择和不选择的价值
            if w >= weights[i - 1]:
                dp[i][w] = max(
                    dp[i][w],
                    dp[i - 1][w - weights[i - 1]] + values[i - 1]
                )
    
    return dp[n][capacity]

# 空间优化版本
def knapsack_optimized(weights, values, capacity):
    n = len(weights)
    
    # 只需要一维数组,从后往前更新避免重复使用
    dp = [0] * (capacity + 1)
    
    for i in range(n):
        for w in range(capacity, weights[i] - 1, -1):
            dp[w] = max(dp[w], dp[w - weights[i]] + values[i])
    
    return dp[capacity]
6. 最大子数组和
# 求连续子数组的最大和
def max_subarray(nums):
    if not nums:
        return 0
    
    # dp[i] 表示以第i个元素结尾的最大子数组和
    dp = [0] * len(nums)
    dp[0] = nums[0]
    
    max_sum = dp[0]
    
    # 状态转移方程:dp[i] = max(nums[i], dp[i-1] + nums[i])
    for i in range(1, len(nums)):
        dp[i] = max(nums[i], dp[i - 1] + nums[i])
        max_sum = max(max_sum, dp[i])
    
    return max_sum

# 空间优化版本
def max_subarray_optimized(nums):
    if not nums:
        return 0
    
    max_sum = nums[0]
    current_sum = nums[0]
    
    for i in range(1, len(nums)):
        current_sum = max(nums[i], current_sum + nums[i])
        max_sum = max(max_sum, current_sum)
    
    return max_sum

实际应用场景

1. 计算机科学领域
  • 算法优化:在递归算法中避免重复计算
  • 字符串处理:文本编辑器的差异比较、拼写检查
  • 图形处理:图像压缩、模式识别
  • 编译器设计:语法分析、代码优化
2. 业务应用
  • 资源分配:项目管理中的任务调度
  • 金融领域:投资组合优化、风险评估
  • 电商推荐:个性化推荐系统
  • 物流运输:路径规划、库存管理
3. 生物信息学
  • DNA序列比对:基因序列相似性分析
  • 蛋白质结构预测:生物分子结构分析
4. 游戏开发
  • AI决策:游戏中的路径寻找
  • 关卡设计:难度平衡计算
5. 网络通信
  • 路由算法:网络数据包的最优路径选择
  • 数据压缩:文件压缩算法优化

动态规划解题模板

def dynamic_programming_solution(problem):
    # 1. 定义状态
    # dp[i] 或 dp[i][j] 表示什么含义
    
    # 2. 初始化边界条件
    # dp[0] = ..., dp[1] = ...
    
    # 3. 状态转移方程
    # for i in range(...):
    #     dp[i] = some_function(dp[i-1], dp[i-2], ...)
    
    # 4. 返回结果
    # return dp[n] 或其他形式
【算法学习】Dynamic Programming动态规划--例题的python实现 关于DP的讲解原文参见:基于java描述的DP讲解 什么时候用动态规划 使用条件 问题的最优解中包含子问题的最优解, 可以使用子问题的最优解构造出原问题的最优解:状态转移方程 重要手段 使用备忘录记录求结果的子问题的解,以减少重复计算 初学者的流程 暴力递归 带备忘录的递归 非递归的动态规划 其中递归解法是自顶向下的(从当前问题规模逐渐减小) 而动态规划是自底向上的(从最小子问题一直计算到... 阅读详情

相关推荐

python 经典算法之--动态规划算法(Dynamic Programming Algorithm)

它通过将原问题分解为若干子问题,逐个求解子问题的最优解,从而得到原问题的最优解。= s2[j-1]时,dp[i][j] = max(dp[i-1][j], dp[i][j-1])。其中,dp[i-1][j]表示不选第i个物品,dp[i-1][j-w[i]]+v[i]表示选择第i个物品。当s1[i-1] == s2[j-1]时,dp[i][j] = dp[i-1][j-1] + 1;初始状态为dp[0][j] = 0和dp[i][0] = 0。初始状态为dp[i][0] = 0和dp[0][j] = 0。

qq_42852699的博客 1375

【强化学习】动态规划(Dynamic Programming, DP)算法

动态规划(Dynamic Programming, DP)是强化学习中基于模型(model-based)方法的核心,通过已知的环境模型(状态转移概率和回报函数)利用贝尔曼方程(Bellman Equation)反复计算值函数,从而推导出最优策略。

欢迎来到我的博客~ 2560

算法 | Five Steps to Dynamic Programming(解决动态规划问题的五个步骤)

动态规划(DP)是最常用的算法之一。它借助Divide and Conquer的思想,将一个问题分解为一个个渐进的subproblems(子问题),最终通过解决这些子问题来得到问题的终极答案。 和recursion(递归)的不同,DP会将所有子问题的答案存在一个表格里,以达到方便提取、提升效率的作用。因此,用递归需要指数时间解决的问题,很多都可以用DP在多项式时间内解决。一个最常见的例子就是计算第...

Spicrab 784

动态规划Dynamic programming详解-最长公共子序列【python】

本文详细介绍了解决最长公共子序列(LCS)问题的动态规划方法。通过定义状态转移方程和初始化条件,我们能有效计算两字符串的LCS长度。此方法具体、高效,适合处理复杂的字符串匹配问题。

10年数据\经营分析经验,现任大厂数据分析负责人 1885

LVDS接口总结--(0)LVDS硬件电路接口

xilinx LVDS接口硬件总结

zidan1412的博客 9721

基于微信小程序的扫码签到系统源码

大等于jdk1.8,大于mysql5.5,idea(eclipse),微信开发者工具。代码注释齐全,没有多余代码,适合学习(毕设),二次开发,包含论文技术相关文档。签到管理:新增签到,点击查看码展示二维码(有时效性)springboot mybatis 小程序。签到管理:查看用户创建的签到,可删除。用户管理:查看注册用户信息,及删除。签到记录:查看用户签到记录:可删除。个人信息:展示个人信息,可修改。统计分析:查看用户,签到数量。签到记录:查看用户签到记录。登录注册(含授权登录)我的签到:查看签到记录。

wfuhui的博客 5224

动态规划(Dynamic Programming)详解

动态规划是一种重要的算法设计方法,广泛应用于解决各种优化问题。通过定义状态、确定状态转移方程、确定初始条件和计算顺序,我们可以高效地求解各种复杂问题。背包问题作为动态规划的经典应用之一,展示了动态规划在实际问题中的强大威力。希望本文能够帮助读者更好地理解动态规划算法,并在实际问题中灵活运用。

Code掘金的博客 1040

在 PyCharm 中使用 Copilot

此外,要在 PyCharm 中使用 GitHub Copilot,您必须有效订阅 Copilot。在 PyCharm 中安装 GitHub Copilot 后,您现在可以将其用作项目的扩展。此外,它很容易安装在不同的 IDE 平台上,您还可以为特定编程语言启用 GitHub 插件。此外,按照以下步骤,您可以轻松地在 PyCharm 中安装 GitHub Copilot。此外,在 IDE 上使用 GitHub Copilot 时,您可以使用一些快捷方式。

一览无遗 1万+

动态规划Dynamic programming详解-背包问题【python】

本文通过对动态规划算法的详细介绍,包括其核心概念、步骤、以及通过具体例子来说明其应用。

10年数据\经营分析经验,现任大厂数据分析负责人 1020

应用处理器(AP)、系统级芯片(SoC)与微控制器(MCU)的区别与联系

应用处理器(AP)、系统级芯片(SoC)与微控制器(MCU)的区别与联系

a_zxswer的博客 1692

15张图详解三方支付:总架构、5大核心业务处理流程、备付金管理

用户可以将银行卡与零钱账户绑定,建立银行结算账户与支付账户的连接,然后将银行账户资金充值到零钱账户中,或将零钱账号中的余额提现至绑定的银行卡。因此,用户在A支付机构的零钱一般只能支付给A支付机构的商户,如支付宝的零钱不能支付给微信的商户。这五大业务的协同运作,使得第三方支付机构这一庞大的支付服务平台能够为市场提供卓越的支付能力。到了结算时间,网联会向备付金集中存管账户提交结算指令,在第三方支付机构备付金集中存管账户内完成最终的结算,并将结算结果及额度变动情况通知给第三方支付机构,具体流程如图13所示。

银行信息系统应用架构详解 1044

动态规划Dynamic programming详解-硬币找零问题【python】

硬币找零问题是一个经典的动态规划问题,在这个问题中我们详细介绍状态转移方程与推导,以及案例与代码

10年数据\经营分析经验,现任大厂数据分析负责人 2133

Ubuntu零基础教学-史上最详Ubuntu20.04安装教程,超级详细,强烈建议收藏!

官网地址:https://www.vmware.com/ 1、VMware Workstation Pro 15.5.1在Windows 10的安装不再介绍了,一路下一步即可。 2、下面详细介绍在VMware 虚拟机里安装Ubuntu 20.04 LTS的步骤

**My Coding Family** 2万+

动态规划Dynamic programming详解-编辑距离问题【python】

编辑距离问题详解包括方程式推导、代码示例、图解,快速掌握动态规划

10年数据\经营分析经验,现任大厂数据分析负责人 1744

MATLAB算法实战应用案例精讲-【数模应用】校准曲线(附MATLAB、python和R语言代码实现)

模型校准曲线(Calibration Curve),也称为可靠性曲线(Reliability Curve)或概率校准曲线(Probability Calibration Curve),是一种评估分类模型输出概率准确性的图形工具。它可以帮助我们理解模型的预测概率是否与实际标签的分布一致。校准曲线通常包括以下步骤:计算模型预测概率:对于测试集中的每个样本,模型会输出一个概率值,表示样本属于正类的概率。将数据分桶:将这些概率值分成若干个等宽的桶(例如10个桶),每个桶中的样本具有相似的预测概率。

qq_36130719的博客 559

大疆前端开发面试题及参考答案(4万字长文)

在前端项目中,难点和性能优化的挑战无处不在。比如在处理复杂交互界面时,实现流畅的动画效果和实时反馈就是一大难点。当界面中有大量元素需要同时进行交互和动态更新,像电商平台的商品筛选和排序功能,不仅要保证操作的即时响应,还要确保界面在各种设备和网络环境下的稳定性,这就需要对事件处理、DOM 操作和数据更新机制有深入理解。在性能优化方面,首屏加载速度是常见的难点。当页面包含大量图片、脚本和样式文件时,如何合理地进行资源压缩、合并与缓存,以减少加载时间,是需要精心考虑的。

大模型大数据攻城狮的专栏 1155

Python三维动态规划(3D Dynamic Programming)

Python三维动态规划(3D Dynamic Programming)

m0_73804671的博客 1770

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

动态规划,Dynamic Programming,python代码实现

Dynamic Programming动态规划问题不带注释的版本带注释的版本 动态规划问题 例如: 你有一个背包,最大承受重量为max_weight,有一些宠物,每个宠物有自己的重量,每个宠物能给你带来的价值不同,现在要背着宠物去旅行,目的是使价值最大化。(其他问题:例如给一定量的本金,去买房子,每个房子的售价和给你带来的收益不一样,求使收益最大化的买房策略) 宠物的重量 宠物名 重量weight cat 1 bird 1 dog 2 tiger 2 elephant 3

weixin_43082343的博客 964

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

钢条切割问题Python实现-动态规划 Dynamic Programming

动态规划问题 问题描述:对于非线性的应用问题,往往只能采用“走一步看一步”的方法解决,即动态规划。解决思路是每一步都选择其中的最优解,即贪心算法。 与分治法类似,通过组合字问题的解来求解全问题。 以钢条切割问题和求解最长公共子序列问题为例。 钢条切割问题 广州市的一家钢条回收厂推出了不同长度的钢条对应不同价格的回收策略,如果小鱼现在有n米长的钢条,应该怎么切割使得销售后收益Rn最大? 长度n 1 2 3 4 5 6 7 8 9 10 价格p 1 5 8 9 10 17 17 20 24 30

DUTwangtaiyu的博客 1943

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

动态规划 Dynamic Programming 分析

(参考这位博主的思想:https://blog.youkuaiyun.com/u013309870/article/details/75193592) 对例题:钢条切割进行解答,并分析三种方法(递归版本 备忘录版本 自底向上动态规划)的效率 import time value=[0,1,5,8,9,10,14,14,20,24,30,37,45,54,64,75,87,100,114,129] exce...

Samzhu 426

动态规划(Dynamic programming)详解

动态规划(Dynamic Programming)是一种解决多阶段决策过程最优化问题的数学方法。它可以用来解决具有重叠子问题和最优子结构性质的问题。动态规划的核心思想是将原问题分解为若干个子问题,并且保存子问题的解,避免重复计算,从而降低时间复杂度。

波吉桑 629

动态规划(Dynamic programming)详解

动态规划是解决复杂问题的有效工具,它通过将问题分解为简单的子问题来减少计算量。掌握动态规划不仅能帮助我们解决实际问题,还能在编程面试中发挥重要作用。希望本文能帮助你对动态规划有更深入的理解和应用。

爱吃雪糕的小布丁的博客 614

背包问题之动态规划(Dynamic Programming)问题Python实现

文章目录动态规划问题背包问题思路talk is cheap, show me the code 动态规划问题 动态规划问题,想法其实很简单,就是根据贝尔曼最优性原理来求解。 如下图: 简单理解:假设图中ABⅡC是最优的轨迹,那么,BⅡC一定是最优的轨迹。这一点应该很容易理解。 证明:假设BⅠC比BⅡC更优,那么AC的最优轨迹就应该为ABⅠC。矛盾。 背包问题 考虑一个场景:当你有去沙漠旅行,你有...

犹有傲霜枝的博客 614

动态规划 Dynamic Programming (python)

动态规划 Dynamic Programming: 寻找最优解 opt ( i ) 任务 i 可以拆分,每次可以选择做任务 i 和不做,做也只做距离任务 i 前面(后面)可选的最近的任务 动态规划的递归算法实现: 1. 从最后一个往前选 2. 每次有两个选择:选,不选 3. 一直倒着往前,第一个是出口 1. 一切循环都可以写成递归 2. 数列的前一二项一般是递归出口 3. 递归函数先写递归出口,再else 动态规划的非递归算法实现: 1. 从第一个往后选 2. 每次有两个选择:选,不选 3. 一直

踩坑记录 588

第6章:动态规划 (Dynamic Programming)

动态规划(DP)是一种高效算法,通过分解问题为重叠子问题并存储解来避免重复计算。其核心特性包括最优子结构和重叠子问题。解题通常遵循五步:定义dp数组、状态转移方程、初始值、遍历顺序和返回值。经典DP问题包括斐波那契数列(状态转移:dp[i]=dp[i-1]+dp[i-2])、0/1背包(空间优化至O(W))、最长递增子序列(优化至O(n log n))和最长公共子序列(状态转移:字符匹配时dp[i][j]=dp[i-1][j-1]+1)。DP在算法面试中占据重要地位,是解决优化问题的利器。

709

数据结构与算法(五)递归与动态规划(Recursion & Dynamic programming)

递归与动态规划(Recursion &amp;amp;amp; Dynamic programming)递归(Recursion)求阶乘斐波那契数列(Fibonacci)汉诺塔(Tower of Hanoi)动态规划(Dynamic programming))图解小结Python实现 递归(Recursion) 普通程序员使用迭代,天才程序员使用递归! 所谓递归,就是有去有回。在数学与计算机科学中,是指在函数的定...

花花的博客 908
上一篇: 动态规划 (Dynamic Programming) 算法概念-JS示例
下一篇: 排序算法 (Sorting Algorithms)-JS示例
香蕉可乐荷包蛋
博客等级 码龄6年 1013粉丝 174原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

香蕉可乐荷包蛋

努力写有用的code

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值