算法与数据结构:动态规划DP

文章目录

      • 动态规划算法全面解析
        • 一、核心思想与基本概念
        • 二、动态规划与其他算法的区别
        • 三、动态规划的解题步骤
        • 四、经典案例解析
          • 1. **斐波那契数列(Fibonacci)**
          • 2. **0-1背包问题(0-1 Knapsack)**
          • 3. **最长公共子序列(LCS)**
        • **五、动态规划的优化技巧**
        • **六、动态规划的应用场景**
        • **七、动态规划与贪心的对比**
        • **八、学习建议**

动态规划算法全面解析

动态规划(Dynamic Programming,DP)是一种通过将复杂问题分解为重叠子问题,并利用子问题的解来高效解决原问题的算法思想。它与分治法类似,但更注重对重复子问题的优化,避免重复计算,从而大幅提升算法效率。

一、核心思想与基本概念
  1. 重叠子问题(Overlapping Subproblems)
    问题可以分解为多次重复出现的子问题。例如斐波那契数列中,计算fib(n)时需要重复计算fib(n-1)fib(n-2)

  2. 最优子结构(Optimal Substructure)
    问题的最优解包含子问题的最优解。例如最短路径问题中,从A到C的最短路径必然包含A到B的最短路径(若B是路径中的节点)。

  3. 状态转移方程
    用数学公式定义子问题之间的关系,是动态规划的核心。例如斐波那契数列的状态转移方程为:
    f i b ( n ) = { 0 , n = 0 1 , n = 1 f i b ( n − 1 ) + f i b ( n − 2 ) , n > 1 fib(n) = \begin{cases} 0, & n=0 \\ 1, & n=1 \\ fib(n-1) + fib(n-2), & n>1 \end{cases} fib(n)= 0,1,fib(n1)+fib(n2),n=0n=1n>1

二、动态规划与其他算法的区别
算法类型核心策略重复子问题处理典型案例
动态规划利用子问题解存储与复用存储结果避免重复计算背包问题、最长公共子序列
分治法将问题分解为独立子问题不存储子问题解归并排序、快速幂
贪心算法每一步选择局部最优解不考虑子问题重叠霍夫曼编码、活动选择问题
三、动态规划的解题步骤
  1. 定义状态
    明确dp[i]表示什么,通常与问题的规模或阶段相关。例如:

    • dp[i]:长度为i的序列的最优解
    • dp[i][j]:二维问题中第i行第j列的状态
  2. 推导状态转移方程
    找出dp[i]dp[i-1]dp[i-2]等子状态的关系,例如:

    • 背包问题:dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i])
    • 最长递增子序列(LIS):dp[i] = max(dp[j] + 1) ,其中j < i且nums[j] < nums[i]
  3. 确定初始条件
    处理最小规模的子问题,例如:

    • dp[0] = 0(空序列的解)
    • dp[i][0] = 0(背包容量为0时无法装物品)
  4. 确定计算顺序
    确保计算dp[i]时,其依赖的子状态已被计算,通常采用自底向上(迭代)的方式。

  5. 获取最终结果
    根据问题要求,从状态数组中提取答案(可能是dp[n]max(dp[1..n])等)。

四、经典案例解析
1. 斐波那契数列(Fibonacci)
  • 问题:计算第n个斐波那契数。
  • 暴力递归:时间复杂度O(2^n),存在大量重复计算。
  • 动态规划解法
    def fib_dp(n):if n <= 1:return ndp = [0] * (n + 1)dp[0], dp[1] = 0, 1for i in range(2, n + 1):dp[i] = dp[i-1] + dp[i-2]return dp[n]
    
  • 优化:只需存储前两个状态,空间复杂度从O(n)降为O(1)
    def fib_optimized(n):if n <= 1:return na, b = 0, 1for _ in range(2, n + 1):a, b = b, a + breturn b
    
2. 0-1背包问题(0-1 Knapsack)
  • 问题:有n个物品,每个物品重量w[i]、价值v[i],背包容量W,求能装的最大价值。
  • 状态定义dp[i][j]表示前i个物品放入容量为j的背包的最大价值。
  • 状态转移
    • 不选第i个物品:dp[i][j] = dp[i-1][j]
    • 选第i个物品(若j >= w[i]):dp[i][j] = dp[i-1][j-w[i]] + v[i]
    • 最终:dp[i][j] = max(不选, 选)
  • 代码实现
    def knapsack(w, v, W):n = len(w)dp = [[0] * (W + 1) for _ in range(n + 1)]for i in range(1, n + 1):for j in range(W + 1):if w[i-1] <= j:dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i-1]] + v[i-1])else:dp[i][j] = dp[i-1][j]return dp[n][W]
    
  • 空间优化:使用一维数组,逆序更新(避免重复使用当前物品):
    def knapsack_optimized(w, v, W):n = len(w)dp = [0] * (W + 1)for i in range(n):for j in range(W, w[i] - 1, -1):dp[j] = max(dp[j], dp[j - w[i]] + v[i])return dp[W]
    
3. 最长公共子序列(LCS)
  • 问题:求两个字符串AB的最长公共子序列长度。
  • 状态定义dp[i][j]表示A[0..i-1]B[0..j-1]的LCS长度。
  • 状态转移
    • A[i-1] == B[j-1]dp[i][j] = dp[i-1][j-1] + 1
    • 否则:dp[i][j] = max(dp[i-1][j], dp[i][j-1])
  • 代码示例
    def lcs_length(text1, text2):m, n = len(text1), len(text2)dp = [[0] * (n + 1) for _ in range(m + 1)]for i in range(1, m + 1):for j in range(1, n + 1):if text1[i-1] == text2[j-1]:dp[i][j] = dp[i-1][j-1] + 1else:dp[i][j] = max(dp[i-1][j], dp[i][j-1])return dp[m][n]
    
五、动态规划的优化技巧
  1. 空间压缩

    • 一维DP:将二维状态数组压缩为一维(如0-1背包的优化)。
    • 滚动数组:仅保留与当前状态相关的前几个子状态(如斐波那契数列)。
  2. 状态转移优化

    • 利用数据结构(如平衡树、单调队列)加速状态转移。
    • 矩阵快速幂:将线性递推关系转化为矩阵乘法,适用于大规模数据。
  3. 记忆化搜索(自顶向下)

    • 用递归+缓存的方式避免重复计算,适合子问题依赖关系复杂的场景。
    def fib_memo(n, memo={}):if n in memo:return memo[n]if n <= 1:memo[n] = nelse:memo[n] = fib_memo(n-1, memo) + fib_memo(n-2, memo)return memo[n]
    
六、动态规划的应用场景
  • 组合优化问题:背包问题、旅行商问题(TSP)、最短路径。
  • 字符串处理:编辑距离、最长回文子串、正则表达式匹配。
  • 数学问题:硬币找零、整数拆分、矩阵链乘法。
  • 概率与统计:股票买卖最佳时机、骰子点数组合。
  • 图论问题:状态压缩DP(如哈密顿路径)。
七、动态规划与贪心的对比
  • 动态规划:考虑所有可能的子问题,确保全局最优,但时间复杂度较高。
  • 贪心算法:每一步选局部最优,可能无法得到全局最优,但效率更高。
  • 案例对比
    • 活动选择问题:贪心可直接选结束时间最早的活动,无需DP。
    • 背包问题:贪心(按单位重量价值选)无法得到最优解,必须用DP。
八、学习建议
  1. 从基础案例入手:先掌握斐波那契、背包、LCS等经典问题。
  2. 多练习状态定义:动态规划的核心难点在于状态转移方程的推导。
  3. 注意边界条件:初始状态的设定直接影响结果正确性。
  4. 分析时间与空间复杂度:优化算法时需平衡两者。
  5. 参考解题模板:许多DP问题有固定的状态设计模式(如区间DP、树形DP)。

动态规划是算法设计中最具挑战性的思想之一,但通过大量练习和总结,能够有效提升解决复杂问题的能力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/85963.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/85963.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Coilcraft电感上的横线是什么意思?电感有方向么?

通常我们会认为电容、电感、电阻这几类无源器件没有方向性&#xff0c;在布局和贴片时可以任意方向放置&#xff0c;也不会在PCB上增加丝印标识说明其方向。与此相互印证的是&#xff0c;电容表面无丝印&#xff0c;无法识别方向&#xff1b;电阻表面一般只有包含阻值大小的数字…

通过Docker挂载nginx并修改页面

1&#xff1a;通过docker创建nginx&#xff1a; 首先关闭原来的Docker&#xff08;防止端口号冲突&#xff09; sudo nginx -s stop 直接启动 Nginx 进程 sudo nginx 启动nginx&#xff1a; docker run -di --namemynginx -p 80:80 nginx cd /etc/nginx docker run -d …

力扣1124. 表现良好的最长时间段

这一题我看到数据范围是10^4&#xff0c;暗自窃喜能用双重循环&#xff0c;看题目是典型的前缀和哈希。不过需要一个转换将大于8小时的转化为1&#xff0c;其他都为-1&#xff0c;方便计算&#xff0c;之前的题目中也有这种方法。 那这样就简单了 class Solution { public:int…

EDA2算法速通(编者崩溃版)

这个内容是用来回忆一下EDA2涉及的算法和解题的主要步骤&#xff1a; 有疑问或发现错误可以私信来讨论 高级综合概述 柏拉图优化&#xff1a;这个是来判断是否有哪些节点能完全被其他节点优化掉。比如&#xff08;1,2&#xff09;这个节点就可以完全优化&#xff08;3,4&…

雷池waf配置第三方登录-钉钉配置详细教程

雷池waf配置第三方登录-钉钉配置详细教程 前往钉钉开放平台https://open.dingtalk.com/ 选择一个登录方式登录钉钉开放平台 选择一个自己所管理的组织 登录成功后点击我的后台 选择应用开发 在钉钉应用下点击创建应用 填写应用名称和应用描述后点击保存 点击网页…

神经网络中的均方误差(Mean Squared Error)详解

引言 在机器学习和神经网络领域&#xff0c;损失函数&#xff08;Loss Function&#xff09;是衡量模型预测值与真实值之间差异的关键指标。均方误差&#xff08;Mean Squared Error, MSE&#xff09;作为一种经典的损失函数&#xff0c;因其简单性、可解释性和数学上的优良性…

day036-lsyncd实时同步服务与网站存储架构

文章目录 1. 实时同步工具2. lsyncd 实时同步服务2.1 环境准备2.2 rsync准备2.2.1 服务端检查2.2.2 客户端检查2.2.3 备份测试 2.3 配置lsyncd2.3.1 安装软件2.3.2 编写配置文件 2.4 测试 3. 案例-网站存储架构3.1 rsync服务配置3.1.1 服务端配置3.1.2 客户端配置 3.2 lsyncd服…

React Native WebView键盘难题:如何让输入框不被键盘遮挡?

写在前面 “明明点击了输入框&#xff0c;键盘却把内容顶得不见踪影&#xff01;” —— 这可能是React Native开发者使用WebView时最头疼的问题之一。 想象一下&#xff1a;你的App内嵌了一个网页表单&#xff0c;用户兴奋地准备填写信息&#xff0c;结果键盘弹出后&#xf…

Web攻防-XSS跨站浏览器UXSS突变MXSSVueReactElectron框架JQuery库写法和版本

知识点&#xff1a; 1、Web攻防-XSS跨站-浏览器&转换-UXSS&MXSS 2、Web攻防-XSS跨站-框架和库-VUE&React&Electron&JQuery 分类&#xff1a; 1、框架或三方库的XSS(Vue、React、Electron、JQuery) 2、浏览器或插件的XSS(UXSS) 3、客户端预览内核的XSS(MXS…

PyTorch 中torch.clamp函数使用详解和实战示例

torch.clamp 是 PyTorch 中的一个非常有用的函数&#xff0c;它可以将张量的每个元素限制在一个指定的范围内&#xff0c;超出范围的元素将被裁剪为边界值。 函数签名&#xff1a; torch.clamp(input, minNone, maxNone, outNone)参数说明&#xff1a; input&#xff1a;输入…

详解Redis数据库和缓存不一致的情况及解决方案

数据库与缓存不一致是分布式系统中常见问题&#xff0c;本质是数据在缓存层和存储层出现版本差异。 一、并发写操作导致不一致&#xff08;最常见&#xff09; 场景描述 线程A更新数据库 → 线程B更新数据库 → 线程B更新缓存 → 线程A更新缓存 结果&#xff1a;缓存中存储的…

湖北理元理律师事务所:企业债务危机的“急诊科”式应对方案

当企业陷入债务危机时&#xff0c;传统“头痛医头”的应对往往加速死亡。本方案基于企业债务重组实务&#xff0c;提炼出 “止血-清创-修复”三阶急救体系&#xff0c;助力企业守住生存底线。 第一阶段&#xff1a;精准止血&#xff08;0-30天关键期&#xff09; 目标&#x…

华为云Flexus+DeepSeek征文|基于Dify构建智能票据信息识别助手

华为云FlexusDeepSeek征文&#xff5c;基于Dify构建智能票据信息识别助手 一、构建智能票据信息识别助手前言二、构建智能票据信息识别助手环境2.1 基于FlexusX实例的Dify平台2.2 基于MaaS的模型API商用服务 三、构建智能票据信息识别助手实战3.1 配置Dify环境3.2 配置Dify工具…

Python实例题:基于联邦学习的隐私保护 AI 系统(分布式学习、隐私计算)

目录 Python实例题 题目 问题描述 解题思路 关键代码框架 难点分析 扩展方向 Python实例题 题目 基于联邦学习的隐私保护 AI 系统&#xff08;分布式学习、隐私计算&#xff09; 问题描述 开发一个基于联邦学习的隐私保护 AI 系统&#xff0c;包含以下功能&#xff…

点点(小红书AI搜索):生活场景的智能搜索助手

1. 产品概述 点点是小红书于2024年12月正式推出的AI搜索助手&#xff0c;由上海生动诗章科技有限公司开发&#xff0c;定位为生活场景搜索工具&#xff0c;聚焦交通、美食、旅游、购物等日常需求&#xff0c;旨在通过即时信息和真实用户分享帮助用户“精准避坑”。 核心特点 …

软件工程概述:核心概念、模型与方法全解析

一、软件工程定义与诞生背景 定义 将系统化、规范化、可度量的方法应用于软件开发、运行和维护的过程&#xff08;IEEE标准&#xff09;。 核心目标&#xff1a;在可控成本下&#xff0c;生产高质量、可维护、满足需求的软件产品。 - 软件开发&#xff1a;需求 → 设计 → 编码…

LVS+Keepalived+nginx

LVSKeepalivednginx 1 安装依赖 sudo yum install ipvsadm keepalived -y 查询是否安装成功 rpm -q -a keepalived 2 配置虚拟IP并安装ipvsadm /etc/sysconfig/network-scripts cp ifcfg-ens33 ifcfg-ens33:1 修改里面配置文件 TYPE"Ethernet" PROXY_METHOD"n…

数据分析实操篇:京东淘宝商品实时数据获取与分析

在电商行业蓬勃发展的当下&#xff0c;数据已然成为驱动决策的核心要素。无论是商家精准把控市场需求、制定营销策略&#xff0c;还是消费者做出明智的购物抉择&#xff0c;都离不开对电商平台商品数据的深入剖析。京东和淘宝作为国内电商领域的两大巨头&#xff0c;汇聚了海量…

微信小程序扫码添加音频播放报错{errCode:10001, errMsg:“errCode:602,err:error,not found param“}

主要流程代码如下&#xff1a; let innerAudioContext wx.createInnerAudioContext() // 提示音 innerAudioContext.autoplay true innerAudioContext.src ../images/scan.mp3 innerAudioContext.onError(function(res){ console.log(onError 开始监听:,res) }) innerAudi…

SVN合并指南,从dev合并部分revision到release指南

dev合并到release 1.进入release的工作区&#xff0c;右击选择Merge 点击Next 2.确认merge来源分支和当前分支 点击Show Log&#xff0c;挑选需要合并的单号 3. 选择需要合并的commit 注意点击Hide no-mergeable revisions&#xff0c;来隐藏掉已经合并的commit 4.选择需…