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

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

动态规划

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/server/115458.html

相关文章

15.2 定义一个prometheus数据存储使用的pv

本节重点介绍 : pv的介绍和存在的意义pv中的核心参数讲解定义一个prometheus数据存储使用的pv pv 存在的意义 PV全称叫做Persistent Volume&#xff0c;持久化存储卷。它是用来描述或者说用来定义一个存储卷的PV是对底层网络共享存储的抽象&#xff0c;将共享存储定义为一种…

【c++】类和对象详解

✅博客主页:爆打维c-CSDN博客​​​​​​ &#x1f43e; &#x1f539;分享c语言知识及代码 来都来了! 点个赞给博主个支持再走吧~&#xff01; 一.类的定义 &#xff08;1&#xff09;类定义格式 class为类定义的关键字&#xff0c;定义一个类格式如下: class 类名{//代码…

B站宋红康JAVA基础视频教程之Chapter13(泛型)

文章目录 1.为什么需要泛型2.泛型的使用案例3.自定义泛型方法4.有限制条件的通配符的使用 1.为什么需要泛型 1.如下&#xff1a;test01中集合中添加元素&#xff0c;不限制类型&#xff0c;字符串的我也能加入&#xff0c;数字的我也能加入&#xff0c;那么我想对集合中做一个取…

【PostgreSQL教程】PostgreSQL 高级篇之 TRANSACTION(事务)

博主介绍:✌全网粉丝20W+,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物联网、机器学习等设计与开发。 感兴趣的可…

【Docker系列】docker缓存详解

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Google 释出 Android 15 源代码

Google 向 Android Open Source Project(AOSP)释出了 Android 15 源代码。 Android 15 将在未来几周内推送给 Pixel 手机&#xff0c;未来几个月推送给三星、摩托罗拉、一加和小米等厂商的兼容手机。 Android 15 的新特性包括&#xff1a;简化 passkey 的登陆&#xff0c;防盗…

C语言---循环程序设计万字总结(2)

选择、循环结构 最简单的结构是 if-else &#xff08;类比日常生活中 如果…否则…&#xff09; 其次&#xff0c; switch&#xff0c; 最后是三大循环结构&#xff0c; while do-while for 选择、循环结构是后续学习的基石&#xff0c; 尤其是与数组和指针 关联性很强 一、选…

docker基本介绍

什么是docker docker是一个开源的容器平台&#xff0c;用于开发、交付和部署 运行应用程序 简单来说 也就是docke他允许开发者将自己的操作环境以及依赖关系打包成一个容器&#xff0c;移动到其他机器上可以供其他人使用&#xff0c;还可以打包成镜像&#xff0c;上传到网络&…

图片太大了怎么压缩?这几种图片压缩方法超级好用!

图片太大了怎么压缩&#xff1f;随着高清摄影与互联网下载的普及&#xff0c;每一张图片都仿佛是一个小型的数据仓库&#xff0c;不断挑战着存储设备的极限&#xff0c;管理这些庞然大物般的图片文件&#xff0c;不仅需要耐心与细心&#xff0c;还可能需要我们掌握一系列复杂的…

【数据结构】二叉树的前中后序遍历以及层序遍历(全解)

文章目录 前言1. 前中后序遍历1.1 遍历规则1.2 代码实现1.3 图解遍历 2. 层序遍历3.结点个数以及高度等4. 判断是否为完全二叉树5. 结语 前言 在前面学习完链式结构的二叉树之后&#xff0c;我们就可以进一步了解二叉树的几种遍历方式了&#xff0c;注意这里就可以深刻的体会到…

【计算机网络】序列化与反序列化

目录 自定义协议应用层什么是协议&#xff1f;网络版计算器 什么是序列化和反序列化重新理解read、write、recv、send和tcp为什么支持全双工网络版计数器Socket.hppTcpSocket.hppservice.hppProtocol.hppNetCal.hppServerMain.ccClientMain.ccMakefile总结 自定义协议 应用层 …

某云彩SRM2.0后台绕过漏洞

文章目录 免责申明搜索语法漏洞描述漏洞复现修复建议 免责申明 本文章仅供学习与交流&#xff0c;请勿用于非法用途&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任 搜索语法 fofa icon_hash"1665918155"漏洞描述 某云采 SRM2.0是一款先…

webpack5 创建多页面应用配置

简单版webpack创建多页面应用&#xff0c;只要把配置文件复制下来&#xff0c;然后npm安装相应插件&#xff0c;正常是能跑起来了 创建 初始化 npm init生成package.json文件安装webpack npm i -D webpack webpack-cli webpack-dev-server创建main.js入口文件和webpack.config…

HTML5中`<span>`标签深入解析

引言 在HTML5中&#xff0c;<span>标签是一个行内元素&#xff0c;用于对文档中的一小部分文本或内容进行分组&#xff0c;以便于应用CSS样式或JavaScript脚本。与块级元素&#xff08;如<div>&#xff09;不同&#xff0c;<span>不会打断文本的流动&#x…

opencv的球面投影

cv::detail::SphericalProjector 在全景图像拼接任务中&#xff0c;可能需要对多个图像进行球面投影以实现无缝拼接。每个cv::detail::SphericalProjector可以负责一个图像的球面投影操作。通过将多个这样的投影器存储在std::vector中&#xff0c;可以对一组图像依次进行投影处…

基于SpringBoot的租房网站系统

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot框架 工具&#xff1a;ECLIPSE 系统展示 首页 管理员功能界面 用户信息界面 预约看房界…

<Rust>egui学习之部件(十一):如何在窗口中添加单选框radiobutton部件?

前言 本专栏是关于Rust的GUI库egui的部件讲解及应用实例分析&#xff0c;主要讲解egui的源代码、部件属性、如何应用。 环境配置 系统&#xff1a;windows 平台&#xff1a;visual studio code 语言&#xff1a;rust 库&#xff1a;egui、eframe 概述 本文是本专栏的第十一篇…

程序员如何写笔记并整理资料?

整理笔记 word。没错&#xff0c;我也看了网上一大堆软件&#xff0c;还有git管理等等。个人认为如果笔记只是记录个人的经验积累&#xff0c;一个word就够了&#xff0c;那些notepad&#xff0c;laTex个人觉得不够简练。word。 1.word可以插入任何文件附件(目前最大的word 20…

mysql数据库8.0小版本原地升级

mysql数据库8.0小版本原地升级 准备工作升级工作停库使用新版本软件启动数据库更新环境变量重启数据库 升级日志 OS release: CentOS 7.9升级前DB version: MySQL 8.0.30数据库升级安装包&#xff1a;mysql-8.0.36-linux-glibc2.12-x86_64.tar.xzMySQL Shell安装包&#xff1a;…

2024.9.4(k8s)

一、前期准备 1、配置主机映射 [rootk8s-master ~]# vim /etc/hosts 192.168.8.168 k8s-master 192.168.8.176 k8s-node1 192.168.8.177 k8s-node2[rootk8s-master ~]# ping k8s-master 2、配置yum源 [rootk8s-master yum.repos.d]# vim kubernetes.repo [kubernetes] n…