Python动态规划:从基础到高阶优化的全面指南

动态规划(Dynamic Programming)是解决复杂优化问题的核心技术,也是算法领域的明珠。本文将深入探讨Python实现动态规划的全方位技术,涵盖基础概念、经典问题、优化技巧和实际工程应用,带您掌握这一强大工具的精髓。

一、动态规划的本质:最优决策的艺术

动态规划不是简单的编程技巧,而是一种系统化的决策方法论。其核心思想是理查德·贝尔曼提出的"最优性原理":一个多阶段决策过程的最优策略具有这样的性质,即无论初始状态和初始决策如何,其余决策必须构成最优策略。

动态规划三大特征:
  1. 重叠子问题:问题可分解为重复计算的子问题

  2. 最优子结构:问题最优解包含子问题最优解

  3. 无后效性:当前决策不影响先前状态

# 斐波那契数列的递归与DP对比
def fib_recursive(n):if n <= 1: return nreturn fib_recursive(n-1) + fib_recursive(n-2)  # 指数级复杂度def fib_dp(n):if n == 0: return 0dp = [0] * (n+1)dp[1] = 1for i in range(2, n+1):dp[i] = dp[i-1] + dp[i-2]  # 线性复杂度return dp[n]# 测试:n=40
%timeit fib_recursive(40)  # 约10秒
%timeit fib_dp(40)        # 约0.5微秒

二、动态规划四步解题框架

步骤1:定义状态
  • 明确dp数组含义

  • 确定状态变量和维度

步骤2:建立状态转移方程
  • 找到状态间递推关系

  • 数学化表示最优子结构

步骤3:初始化边界条件
  • 设置初始状态值

  • 处理特殊情况

步骤4:确定计算顺序
  • 自底向上或自顶向下

  • 确保无后效性

def coin_change(coins, amount):"""零钱兑换问题:最少硬币数"""# 步骤1:定义状态 - dp[i]表示金额i的最小硬币数dp = [float('inf')] * (amount+1)# 步骤2:初始化边界 - 金额0需要0枚硬币dp[0] = 0# 步骤3:状态转移for coin in coins:for i in range(coin, amount+1):dp[i] = min(dp[i], dp[i-coin] + 1)# 步骤4:返回结果return dp[amount] if dp[amount] != float('inf') else -1# 测试
print(coin_change([1, 2, 5], 11))  # 输出:3 (5+5+1)

三、经典动态规划问题精解

3.1 背包问题:组合优化的基石

0-1背包问题

def knapsack_01(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(1, capacity+1):if weights[i-1] <= w:dp[i][w] = max(dp[i-1][w], dp[i-1][w-weights[i-1]] + values[i-1])else:dp[i][w] = dp[i-1][w]return dp[n][capacity]# 测试
weights = [2, 3, 4, 5]
values = [3, 4, 5, 6]
capacity = 8
print(knapsack_01(weights, values, capacity))  # 输出:10 (物品2+4)

完全背包问题

def knapsack_unbounded(weights, values, capacity):dp = [0] * (capacity+1)for w in range(1, capacity+1):for i in range(len(weights)):if weights[i] <= w:dp[w] = max(dp[w], dp[w-weights[i]] + values[i])return dp[capacity]# 测试
print(knapsack_unbounded(weights, values, capacity))  # 输出:12 (物品1*4)
3.2 最长公共子序列(LCS)
def longest_common_subsequence(text1, text2):m, n = len(text1), len(text2)# dp[i][j] 表示text1[0:i]和text2[0:j]的LCS长度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])# 回溯构造LCSlcs = []i, j = m, nwhile i > 0 and j > 0:if text1[i-1] == text2[j-1]:lcs.append(text1[i-1])i -= 1j -= 1elif dp[i-1][j] > dp[i][j-1]:i -= 1else:j -= 1return dp[m][n], ''.join(reversed(lcs))# 测试
text1 = "abcde"
text2 = "ace"
length, seq = longest_common_subsequence(text1, text2)
print(f"长度: {length}, 序列: {seq}")  # 长度: 3, 序列: "ace"
3.3 最短编辑距离
def min_edit_distance(word1, word2):m, n = len(word1), len(word2)dp = [[0]*(n+1) for _ in range(m+1)]# 初始化边界for i in range(1, m+1):dp[i][0] = ifor j in range(1, 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]# 测试
print(min_edit_distance("horse", "ros"))  # 输出:3 (h->r, 删o, 删e)

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

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

相关文章

视觉大模型部署实践篇(Docker+dify+ollama安装)

一、概述 目的:实现一个本地化部署的大模型,通过工作流对图像进行一些处理。基于此,我选择了Docker+Dify+Ollama的部署。 具体实现逻辑:Docker来运行dify,dify用来绘制大模型的工作流或者rag等,Ollama用来部署本地大模型,dify调用Ollama部署的大模型进行推理。 二、Dock…

服务器启动日志等级

目录 标准日志等级 服务器启动阶段常见日志 日志配置建议 常见服务器/工具的日志等级配置方式 ET框架 Apache/Nginx 等 Web 服务器 Docker 容器 服务器启动过程中的日志等级是帮助开发者和运维人员理解系统状态的重要工具。常见的日志等级及其含义如下&#xff1a; 标准…

linux_centos7安装jdk8_采用jdk安装包安装

你问我为什么不用yum? 我yum安装不了&#xff0c;我也解决不了qwq. 文章目录一.下载安装包1.找到安装包下载位置2.上传安装包到linux3.解压jdk安装包4.配置环境一.下载安装包 1.找到安装包下载位置 去官网找到你要下载jdk版本&#xff1a; Oracle官网 下面演示安装jdk8的&am…

Linux驱动23 --- RkMedia 使用

目录 一、上电自动挂载 二、RkMedia 2.1 认识 RkMedia rtsp rtmp RTSP 和 RTMP 的选择 2.2 安装 VLC 2.2 RkMedia 例程使用 一、上电自动挂载 cd /etc/init.d/ vi Smyprofile.sh 添加这个内容 #!/bin/sh ifconfig eth0 192.168.66.88 mount -t nfs 192.168.66.66…

Linux:线程同步与线程互斥

线程互斥竞态条件当多个线程&#xff08;或进程&#xff09;并发访问和操作同一个共享资源&#xff08;如变量、文件、数据库记录等&#xff09;时&#xff0c;最终的结果依赖于这些线程执行的相对时序&#xff08;即谁在什么时候执行了哪条指令&#xff09;。 由于操作系统调度…

HTML 常用标签速查表

HTML 常用标签速查表 &#x1f9f1; 结构类标签 标签含义用途说明<html>HTML文档根元素所有HTML内容的根节点<head>头部信息放置元信息&#xff0c;如标题、引入CSS/JS等<body>页面内容主体所有可视内容的容器&#x1f4dd; 文本与标题标签 标签含义用途说…

1.gradle安装(mac)

1.下载二进制包 官网下载&#xff1a;Gradle Releases 国内镜像&#xff08;腾讯云&#xff09;&#xff1a;https://mirrors.cloud.tencent.com/gradle/ 2.解压并配置环境变量 解压到指定目录&#xff08;示例&#xff1a;/opt/gradle&#xff09; sudo mkdir -p /opt/gr…

Rust赋能土木工程数字化

基于Rust语言在数字化领域应用 基于Rust语言在土木工程数字 以下是基于Rust语言在土木工程数字化领域的30个实用案例,涵盖结构分析、BIM、GIS、传感器数据处理等方向。案例均采用Rust高性能、安全并发的特性实现,部分结合开源库或算法。 结构分析与计算 有限元分析框架 使…

KTH5791——3D 霍尔位置传感器--鼠标滚轮专用芯片

1 产品概述 KTH5791是一款基于3D霍尔磁感应原理的鼠标滚轮专用芯片&#xff0c;主要面向鼠标滚轮的旋转的应用场景。两个 专用的正交输出使该产品可直接替代机械和光学旋转编码器的输出方式&#xff0c;使得鼠标磁滚轮的应用开发工作极简 化即兼容目前所有鼠标的滚轮输出方式。…

决策树(Decision Tree)完整解析:原理 + 数学推导 + 剪枝 + 实战

1️⃣ 什么是决策树&#xff1f;决策树&#xff08;Decision Tree&#xff09;是一种常见的监督学习方法&#xff0c;可用于分类和回归。 其基本思想是&#xff1a;通过特征条件的逐层划分&#xff0c;将数据集分割成越来越“纯净”的子集&#xff0c;直到子集中的样本几乎属于…

C语言:20250728学习(指针)

回顾/*************************************************************************> File Name: demo01.c> Author: 阮> Description: > Created Time: 2025年07月28日 星期一 09时07分52秒**********************************************************…

esp32s3文心一言/豆包(即火山引擎)大模型实现智能语音对话--流式语音识别

一、引言 在之前的帖子《Esp32S3通过文心一言大模型实现智能语音对话》中&#xff0c;我们介绍了如何使用Esp32S3微控制器与文心一言大模型实现基本的智能语音对话功能&#xff0c;但受限于语音识别技术&#xff0c;只能处理2-3秒的音频数据。为了提升用户体验&#xff0c;满足…

面试150 最长递增子序列

思路 定义 dp[i] 表示以第 i 个元素结尾的最长递增子序列的长度&#xff0c;初始时每个位置的最长子序列长度为 1。然后通过双重循环遍历每一对元素 j < i&#xff0c;如果 nums[i] > nums[j]&#xff0c;说明 nums[i] 可以接在 nums[j] 的递增序列之后&#xff0c;更新 …

TCP 套接字--服务器相关

1.创建 TCP 套接字int server_sockfd socket(AF_INET,SOCK_STREAM, 0);函数原型&#xff1a;#include <sys/socket.h>int socket(int domain, int type, int protocol);domain协议族&#xff08;地址族&#xff09;AF_INET&#xff08;IPv4&#xff09;type套接字类型SO…

六、搭建springCloudAlibaba2021.1版本分布式微服务-admin监控中心

前言Spring Boot Actuator 是 spring-boot 自带监控功能 &#xff0c;可以帮助实现对程序内部运行情况监控&#xff0c;比如监控状况、Bean 加载情况、环境变量、日志信息、线程信息等。 Spring Boot Admin是一个针对 spring-boot 的 actuator 接口进行 UI 美化封装的监控工具。…

轻量级远程开发利器:Code Server与cpolar协同实现安全云端编码

前言&#xff1a;作为一款专为Web环境设计的VS Code托管方案&#xff0c;Code Server通过精简架构重新定义了远程开发体验。其核心优势在于将完整的编辑器功能封装于轻量容器中——仅需不到200MB内存即可运行基础服务&#xff0c;并支持在树莓派等低性能设备上流畅操作。系统采…

图论:最小生成树

今天要介绍两中最小生成树的算法&#xff0c;分别是prim算法和kruskal算法。 最小生成树是所有节点的最小连通子图&#xff0c;即&#xff1a;以最小的成本&#xff08;边的权值&#xff09;将图中所有节点链接到一起。 图中有n个节点&#xff0c;那么一定可以用n-1条边将所有节…

haproxy七层代理

1、负载均衡Load Balance(LB) 概念 负载均衡&#xff1a;是一种服务或基于硬件设备等实现的高可用反向代理技术&#xff0c;负载均衡将特定的业务(web服务、网络流量等)分担给指定的一个或多个后端特定的服务器或设备&#xff0c;从而提高了 公司业务的并发处理能力、保证了业务…

【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 微博文章数据可视化分析-点赞区间实现

大家好&#xff0c;我是java1234_小锋老师&#xff0c;最近写了一套【NLP舆情分析】基于python微博舆情分析可视化系统(flaskpandasecharts)视频教程&#xff0c;持续更新中&#xff0c;计划月底更新完&#xff0c;感谢支持。今天讲解微博文章数据可视化分析-点赞区间实现 视频…

Redis实战(3)-- 高级数据结构zset

有序集合&#xff08;ZSET&#xff09;&#xff1a;可以用作相关有序集合相对于哈希、列表、集合来说会有一点点陌生,但既然叫有序集合,那么它和集合必然有着联系,它保留了集合不能有重复成员的特性,但不同的是,有序集合中的元素可以排序。但是它和列表使用索引下标作为排序依据…