数学建模笔记——动态规划

数学建模笔记——动态规划

动态规划

1. 模型原理

动态规划是运筹学的一个分支,通常用来解决多阶段决策过程最优化问题动态规划的基本想法就是将原问题转换为一系列相互联系的子问题,然后通过逐层地推来求得最后的解。目前,动态规划常常出现在各类计算机算法竞赛或者程序员笔试面试中,在数学建模中出现的相对较少,但这个算法的思想在生活中非常实用,会对我们解决实际问题的思维方式有一定启发。

动态规划组成部分:

  1. 确定状态:解动态规划的时候需要开一个数组,数组的每个元素需要明确代表什么,类似于确定数学题中X、Y的含义
  2. 转移方程:把状态表达成方程
  3. 初始条件和边界情况
  4. 计算顺序

2. 典型例题

2.1 例1 凑硬币

你有三种硬币,分别面值2元、5元和7元,每种硬币都有足够多,买一本书需要27元,如何用最少的硬币组合起来正好付清,不需要对方找钱

  1. 确定状态

    • 最后一步:

      虽然我们不知道最优策略是什么,但是最优策略肯定是有k校硬币, a 1 , a 2 , . . . . . . a k a_1,a_2,......a_k a1,a2,......ak加起来面值为27,所以一定存在有最后一枚硬币: a k a_k ak,除了这枚硬币,前面的面值加起来是 27 − a k 27-a_k 27ak,两个关键点:

      • 我们不关心前面的 k − 1 k-1 k1枚硬币是怎么拼出 27 − a k 27-a_k 27ak的(可能有很多种拼法),而且我们现在甚至还不知道 a k a_k ak k k k是多少,但我们可以确定前面的硬币拼出了 27 − a k 27-a_k 27ak
      • 因为是最优策略,所以拼出 27 − a k 27-a_k 27ak的硬币数一定要最少,否则就不是最优策略
    • 子问题:

      • 最少可以用多少枚硬币拼出 27 − a k 27-a_k 27ak
      • 原问题是最少可以用多少枚硬币可以拼出27
      • 我们将原问题可以转化为一个规模更小的子问题: 27 − a k 27-a_k 27ak
    • 状态:

      我们可以设状态 f ( x ) = 最少用多少枚硬币拼出 x f(x)=最少用多少枚硬币拼出x f(x)=最少用多少枚硬币拼出x

  2. 转移方程

    对于任意 x x x
    f [ x ] = m i n { f [ x − 2 ] + 1 , f [ x − 5 ] + 1 , f [ x − 7 ] + 1 } f[x]=min\{f[x-2]+1,f[x-5]+1,f[x-7]+1\} f[x]=min{f[x2]+1,f[x5]+1,f[x7]+1}

  3. 初始条件和边界情况

    • 转移方程有两个问题
      • x − 2 , x − 5 , 或 x − 7 x-2,x-5,或x-7 x2,x5,x7小于0怎么办
      • 什么时候停下来
    • 所以:
      • 如果不能拼出Y,那么就定义 f [ Y ] = f[Y]= f[Y]=正无穷,例如 f [ − 1 ] = f [ − 2 ] = f [ − 3 ] = ⋯ = f[-1]=f[-2]=f[-3]=\cdots= f[1]=f[2]=f[3]==正无穷
      • 所以 f [ 1 ] = min ⁡ { f [ − 1 ] + 1 , f [ − 4 ] + 1 , f [ − 6 ] + 1 } = f[1]=\operatorname*{min}\{f[-1]+1,f[-4]+1,f[-6]+1\}= f[1]=min{f[1]+1,f[4]+1,f[6]+1}=正无穷,表示拼不出来
      • 初始条件 f [ 0 ] = 0 f[0]=0 f[0]=0
  4. 计算顺序

    • 拼出 x x x所需要的最少硬币数: f [ x ] = m i n { f [ x − 2 ] + 1 , f [ x − 5 ] + 1 , f [ x − 7 ] + 1 } f[x]=min\{f[x-2]+1,f[x-5]+1,f[x-7]+1\} f[x]=min{f[x2]+1,f[x5]+1,f[x7]+1}
    • 初始条件: f [ 0 ] = 0 f[0]=0 f[0]=0
    • 然后计算 f [ 1 ] , f [ 2 ] , . . . , f [ x ] f[1],f[2],...,f[x] f[1],f[2],...,f[x]

2.2 例2 背包问题

有一个小偷去偷东西,他的背包可以容纳总重量为 W W W的物品,现在有 n n n件物品,每件物品的重量为 w i w_i wi, 价值为 v i v_i vi ,求能够放进背包的物品的最大价值。

  1. 状态: d p [ i ] [ j ] dp[i][j] dp[i][j]表示前 i i i件物品放入容量为 j j j的背包中所获得的最大价值

  2. 状态转移方程:对于第 i i i件物品,可以选择放或不放

    • 如果不放,那么 d p [ i ] [ j ] = d p [ i − 1 ] [ j ] dp[i][j]=dp[i-1][j] dp[i][j]=dp[i1][j]

    • 如果放,那么 d p [ i ] [ j ] = d p [ i − 1 ] [ j − w i ] + ν i dp[i][j]=dp[i-1][j-w_i]+\nu_i dp[i][j]=dp[i1][jwi]+νi

    • 选择获得最大价值的情况,即
      d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i − 1 ] [ j − w i ] + v i ) dp[i][j]\:=\:max(dp[i-1][j],dp[i-1][j-w_i]\:+\:v_i) dp[i][j]=max(dp[i1][j],dp[i1][jwi]+vi)

  3. 初始条件:

    • d p [ 0 ] [ 0 ] = 0 dp[ 0] [ 0] = 0 dp[0][0]=0,将前0个物品放入容量为0的背包中能获得的最大价值为0
    • 如果容量为 0,则无法放入任何物品, d p [ i ] [ 0 ] = 0 dp[i][0]=0 dp[i][0]=0
    • 如果没有物品可选,则无法放入任何物品, d p [ 0 ] [ j ] = 0. dp[0][j]=0. dp[0][j]=0.
  4. 求解顺序:从第一个物品开始,求解到 n n n

最终, d p [ n ] [ W ] dp[n][W] dp[n][W]即为问题的解

python_89">3. python代码实现

3.1 例1

python">def coinChange(n):"""用于计算找零的最少硬币数Args:n (int): 需要找零的金额return:int: 最少硬币数,如果无法找零则返回-1"""dp = [float('inf')]*(n+1)  # 初始化动态规划数组dp[0] = 0  # 金额为0时,最少硬币数为0for i in range(1, n+1):for j in [2, 5, 7]:if i >= j:dp[i] = min(dp[i], dp[i-j]+1)if dp[n] == float('inf'):return -1else:return dp[n]n = int(input("请输入需要找零的金额:"))
res = coinChange(n)
print("最少硬币数为:", res)

测试结果:

请输入需要找零的金额:27
最少硬币数为: 5

3.2 例2

python">def knapsack(weights, values, capacity):"""用于求解0-1背包问题动态规划算法Args:weights (int): 物品的重量列表values (int): 物品的价值列表capacity (int): 背包的容量return:int: 背包能装的最大价值"""n = len(weights)  # 物品的数量dp = [[0 for j in range(capacity+1)] for i in range(n+1)]  # 初始化动态规划数组# 动态规划求解过程for i in range(1, n+1):for j in range(1, capacity+1):if j < weights[i-1]:dp[i][j] = dp[i-1][j]else:dp[i][j] = max(dp[i-1][j], dp[i-1][j-weights[i-1]]+values[i-1])return dp[n][capacity]w = input("请输入物品的重量列表(用逗号隔开):")
v = input("请输入物品的价值列表(用逗号隔开):")
weights = [int(i) for i in w.split(",")]
values = [int(i) for i in v.split(",")]
c = int(input("请输入背包的容量:"))
res = knapsack(weights, values, c)
print("背包能装的最大价值为:", res)

输入及输出:

请输入物品的重量列表(用逗号隔开):1,2,3
请输入物品的价值列表(用逗号隔开):3,4,5
请输入背包的容量:5
背包能装的最大价值为: 9
请输入物品的重量列表(用逗号隔开):1,2,3
请输入物品的价值列表(用逗号隔开):4,5,6
请输入背包的容量:5
背包能装的最大价值为: 11

http://www.ppmy.cn/ops/111368.html

相关文章

Frida 脚本抓取 HttpURLConnection 请求和响应

引入 Java 类&#xff1a; 引入 okhttp3.OkHttpClient、okhttp3.OkHttpClient$Builder、okhttp3.Interceptor、okhttp3.ResponseBody 等类。 创建自定义拦截器&#xff1a; 通过 Java.registerClass 创建自定义拦截器 MyInterceptor。拦截器中重写 intercept 方法&#xff0…

基于 PyTorch 和 TensorFlow 的口罩检测与人脸识别系统

在后疫情时代&#xff0c;口罩检测成为了人脸识别系统的一个重要功能。如何在戴口罩的情况下准确识别身份&#xff0c;是一个技术难点。本文将介绍如何利用 PyTorch 和 TensorFlow 实现一个包含口罩检测功能的简单人脸识别系统&#xff0c;结合了Facenet 模型用于特征提取&…

docker-实战——监控环境部署

文章目录 介绍安装教程软件版本主机准备脚本配置修改主机配置免密配置配置修改脚本执行网络联通检查部署节点初始化监控部署服务检查后台检查Prometheus检查Grafana检查面板检查总结版本说明下载地址介绍 通过ansible快速使用docker方式安装监控集群集群因涉及网速问题、使用离…

在grafana上配置显示全部node资源信息概览

在grafana上配置显示全部node资源信息概览&#xff0c;便于巡检 1&#xff0c;注册grafana官网账号&#xff1a;Grafana dashboards | Grafana Labs&#xfeff; 2、寻找可以展示所有node资源概览信息的dashboard&#xff0c;并下载支持prometheus数据源的dashboard&#xff…

ai 回答HFS是什么 HTTP的文件服务器是什么

HFS&#xff08;HTTP File Server&#xff09;是一个基于HTTP协议的文件服务器软件&#xff0c;它允许用户通过浏览器访问和共享计算机上的文件。HFS的特点包括界面简洁直观、易于安装和配置、支持虚拟文件系统、多种权限设置等。用户可以轻松地在本地网络或互联网上共享文件和…

怎么选择适合的服务器

大家都知道&#xff0c;不管是公司还是个人&#xff0c;在数字化浪潮已经席卷全球的环境下&#xff0c;大家对服务器的需求是日渐增长的。很多人在买服务器的时候&#xff0c;多少都有点选择困难&#xff0c;今天我们就来对比下物理服务器和弹性云服务器&#xff0c;看看选哪个…

完整指南:CNStream流处理多路并发框架适配到NVIDIA Jetson Orin (四) 运行、调试、各种问题解决

目录 1 调试jetson-mpeg视频解码模块 1.1 修改config.json 1.2 Picture size 0x0 is invalid 1.3 Process(): Send package failed. Maximum number of attempts reached 1.4 Picture size 2239821608x65535 is invalid 1.5 保存h264文件解码之后的测试图片 1.6 保存RTS…

Kubernetes+Minio+Velero:终极备份解决方案

转载&#xff1a;KubernetesMinioVelero&#xff1a;终极备份解决方案 1.Velero介绍 1.1 为何需要Velero 对于 Kubernetes 集群的备份&#xff0c;其实定期备份etcd数据库就可以了&#xff0c;但etcd的备份通常是针对整个集群进行备份与恢复&#xff0c;如果只是想恢复某个特…

Java进阶13讲__补充2/2

1. 设计模式 1.1 什么是设计模式 1.2 单例设计模式 package com.itheima.a_单例_饿汉式;public class T1 {public static void main(String[] args) {new Thread(new Runnable() {Overridepublic void run() {Demo demo Demo.createDemo();System.out.println(Thread.curr…

CAN BUS

CAN BUS 原理 网上资料非常丰富&#xff0c;是车载系统主要BUS之一。 我们关注如下方面 can bus 是什么网络结构CAN BUS 协议ECU node实现其他 What is CAN Bus? Control Area Network (CAN) bus is a serial communication protocol that allows devices to exchange dat…

Go入门语法

1.转义符 1&#xff09; \t &#xff1a;一个制表位&#xff0c;实现对齐功能 2&#xff09;\n &#xff1a;换行符 3&#xff09;\ &#xff1a;一个 4&#xff09;" &#xff1a;一个" 5&#xff09;\r &#xff1a;一个回车不换行&#xff08;r后覆盖当前行最前面…

算法岗/开发岗 实况

深信服算法岗一面 第一题 树的直径有哪些解法 两次dfs和树形dp&#xff0c;讲了一下树形dp的思路 因为我的简历写的比较少&#xff0c;所以面试官问我一些个人信息和擅长哪方面。 我说&#xff1a;ACM大一下打到大三&#xff0c;然后去考研。dp写的多一点&#xff0c;还有思维…

AndroidManifest.xml文件的重要信息

AndroidManifest.xml文件详解 一、概述 AndroidManifest.xml文件是Android应用的核心配置文件&#xff0c;它位于应用程序的根目录下&#xff08;通常在app/src/main/文件夹中&#xff09;。这个文件对于Android系统来说至关重要&#xff0c;因为它提供了关于应用程序的所有必…

如何 吧一个 一维数组 切分成相同等分,一维数组作为lstm的输入(三维数据)的数据预处理 collate_fn的应用

要将一个一维数组切分成相同等分&#xff0c;你可以使用 Python 的内置功能或者 NumPy 库&#xff08;如果你处理的是数值数据&#xff09;。以下是几种不同的方法&#xff1a; 方法3 pad_sequence 结合dataloader 应该是最佳方案 ### 方法 1: 使用 Python 的内置切片功能 如果…

设计模式 装饰模式(Decorator Pattern)

装饰器模式简绍 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其结构。这种类型的设计模式属于结构型模式&#xff0c;它是作为现有的类的一个包装。 装饰器模式的基本结构 装饰器模式的基本结构如下&…

利用shuji还原webpack打包源码

0 前言 前段时间做一个银行的项目&#xff0c;是在别人已经打过好多次的基础上继续打&#xff0c;而且时间很短&#xff0c;也是没办法要有产出&#xff0c;这个银行很多站点都是webpack打包&#xff0c;就新学了一个点&#xff1a;利用shuji获取webpack打包站源码&#xff08…

【VMvare虚拟机-Ubuntu】解决内存不足问题

VMvare虚拟机-Ubuntu&#xff1a;解决内存不足问题 1 虚拟机额度磁盘分配2 原因&#xff1a;扩展内存导致无法正常开机3 解决方案&#xff1a;硬盘扩容后无法正常开机3.1 选择镜像文件3.2 设置光盘启动优先3.3 在 live 系统中扩容分区3.4 开启虚拟机 另&#xff1a;VMWare虚拟机…

.json文件的C#解析,基于Newtonsoft.Json插件

目录 1. 前言 2. 正文 2.1 问题 2.2 解决办法 2.2.1 思路 2.2.2 代码实现 2.2.3 测试结果 3. 备注 1. 前言 天气晚来秋,这几天天气变凉了,各位同学注意好多穿衣服。回归正题 由于需要,需要将json的配置里面的调理解析出来,做成接口,以便于开发。 2. 正文 2.1 …

GO Govaluate

govaluate 是一个用于在 Go 语言中动态求值表达式的库。它允许你解析和评估字符串形式的表达式&#xff0c;这些表达式可以包含变量、函数以及逻辑、算术和比较操作。它非常适合在运行时处理复杂的逻辑规则和条件表达式&#xff0c;而不需要重新编译代码。 安装 govaluate go…

Jacoco的XML报告详解

使用jacococli完成jacoco测试报告生成后,会看到有一个.xml结尾的文件,这个就是xml格式的覆盖率报告。除了xml还有csv、html格式的报告,本文进介绍xml报告。 DTD文件 在介绍jacoco的xml报告之前,我们应该先看一下对应的DTD文件的内容。(DTD的全称为Document Type Definitio…