python 动态规划的应用;斐波那契数列,最优解,最优子序列

news2024/12/24 21:11:51

一、动态规划概念

动态规划(Dynamic Programming,DP)是运筹学的一个分支,是求解决策过程最优化的过程。20世纪50年代初,美国数学家贝尔曼(R.Bellman)等人在研究多阶段决策过程的优化问题时,提出了著名的最优化原理,从而创立了动态规划。动态规划的应用极其广泛,包括工程技术、经济、工业生产、军事以及自动化控制等领域,并在背包问题、生产经营问题、资金管理问题、资源分配问题、最短路径问题和复杂系统可靠性问题等中取得了显著的效果 [1]  。[2] 

[1]  许国根,赵后随,黄智勇.最优化方法及其MATLAB实现:许国根,赵后随,黄智勇,2018-07:91

[2]  Thomas H. Cormen,Charles E. Leiserson,Ronald L. Rivest,Clifford Stein.Introduction to Algorithms, Third Edition:麻省理工大学出版社,2009

简单理解:动态规划就是在有多个子序列作为解的时候,去寻找出最优的组合作为最优解。

二、动态规划的例子

1. 例子1:寻找两个字符串的最长公共子串?

如str_01 = '世界杯半决赛真好看',str_02 = '决赛比半决赛更好看'

import numpy as np

def dynamic_p(s1, s2) -> list:
    r, c = len(s1), len(s2)
    dp = [[0] * (c+1) for _ in range(r+1)] #构建转移方程矩阵
    for row in range(r):
        for col in range(c):
            #转移方程表达式
            if s1[row] == s2[col]:
                dp[row+1][col+1] = dp[row][col] + 1    # 对左上角CELL值+1
            else:
                # 匹配不成功清0,这里可以不用到else,因为默认值就为0
                dp[row+1][col+1] = 0
    return dp

str_01 = '世界杯半决赛真好看'
str_02 = '决赛比半决赛更真好看'
arr = []
dp = dynamic_p(str_01, str_02)

for i in dp:
    arr.extend(i)
    print(i)                                           # 打印数组
#最长子串的位置
dp_array = np.array(dp)
res = []
for i in np.where(dp_array == np.max(dp_array))[0]:
    result = str_01[i - np.max(dp_array):i]
    res.append(result)
print(f"最长公共子串长度为:{max(arr)}")
print(f"最长公共子串为:{res}")

 动态规划策略:动态规划中本阶段的状态往往是上一阶段状态和上一阶段决策的结果。若给定了第K阶段的状态Sk以及决策uk(Sk),则第K+1阶段的状态Sk+1也就完全确定。也就是说Sk+1与Sk,uk之间存在一种明确的数量对应关系,记为Tk(Sk,uk),即有Sk+1= Tk(Sk,uk)。 这种用函数表示前后阶段关系的方程,称为状态转移方程。在上例中状态转移方程为 Sk+1= uk(Sk) 。

转移方程:

 2.例子2:背包空间问题,即组合最优化问题?

假设王同学要去野营,他准备了以下物品:

背包最大容量为6斤,装不下所有的东西,只能从这堆东西中挑选组合价值最高的物品,这是典型的最优组合问题:

方法一:

思路:构建一个解题矩阵,(物品)*(背包空间),然后计算每个矩阵位点的最优解,即价值最大组合。

代码;

#完整代码
def dynamic_p() -> list:
    items = [  									 # 物品项
        {"name": "水", "weight": 3, "value": 10},
        {"name": "书", "weight": 1, "value": 3},
        {"name": "食物", "weight": 2, "value": 9},
        {"name": "小刀", "weight": 3, "value": 4},
        {"name": "衣物", "weight": 2, "value": 5},
        {"name": "手机", "weight": 1, "value": 10}
    ]
    max_capacity = 6                             # 约束条件为 背包最大承重为6
    dp = [[0] * (max_capacity + 1) for _ in range(len(items) + 1)]

    for row in range(1, len(items) + 1):         # row 代表行
        for col in range(1, max_capacity + 1):   # col 代表列
            weight = items[row - 1]["weight"]    # 获取当前物品重量
            value = items[row - 1]["value"]      # 获取当前物品价值
            if weight > col:                     # 判断物品重量是否大于当前背包容量
                dp[row][col] = dp[row - 1][col]  # 大于直接取上一次最优结果 此时row-1代表上一行
            else:
                # row-1 为上一行,row为本行,若要重复拿取,只需要在目前物品所在的那一行寻找最优解即可
                dp[row][col] = max(value + dp[row][col - weight], dp[row - 1][col])
    return dp


dp = dynamic_p()
for i in dp:                                     # 打印数组
    print(i)

print(dp[-1][-1])                                # 打印最优解的价值和

方法二:通过平均最大价值来计算

思路:构建物品矩阵,计算每件物品的平均价值,选取最优的放进包里

import numpy as np

items = [  									 # 物品项
        {"name": "水", "weight": 3, "value": 10},
        {"name": "书", "weight": 1, "value": 3},
        {"name": "食物", "weight": 2, "value": 9},
        {"name": "小刀", "weight": 3, "value": 4},
        {"name": "衣物", "weight": 2, "value": 5},
        {"name": "手机", "weight": 1, "value": 10}
    ]

#物品词典
dic_name ={i['name']:index for index,i in enumerate(items)}
#构建item矩阵
item2array = np.zeros((6,4),dtype='float')
for i,j in enumerate(items):
    item2array[i][0] = float(dic_name.get(j['name']))
    item2array[i][1] = float(j['weight'])
    item2array[i][2] = float(j['value'])
    item2array[i][3] = item2array[i][2]/item2array[i][1]

#矩阵排序
item2array_01 = item2array[np.lexsort(-item2array.T)]

#剩余空间v_remain
v_remain = 6
#目前背包中物品的价值value
value = 0
#背包中的物品re_lis
re_lis = []
for i in item2array_01:
    if i[1] <= v_remain:
        v_remain = v_remain - i[1]
        value = value + i[2]
        for m in dic_name.keys():
            if float(dic_name[m]) == float(i[0]):
                re_lis.append(m)
print(v_remain,value,re_lis)

例子3:斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34...

斐波纳契数列转移方程可以写成:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=2,n∈N*)
方法1:

def febonaci(n):
    a,b = 0,1
    for i in range(n):
        a,b = b,a+b
        print(a)
febonaci(5)

 方法2:

def febonaci(n):
    a,b =0,1
    i = 0
    while i < n:
        print(a)
        a,b = b,a+b
        i+=1

方法3: 

def febonaci(n):
    lis_num = []
    for i in range(n):
        if i==0 or i==1:
            lis_num.append(i)
        else:
            lis_num.append(lis_num[-1]+lis_num[-2])
    return lis_num

 方法4: 

def febonaci(n):
    lis_num = []
    i = 0
    while i < n:
        if i==0 or i==1:
            lis_num.append(i)
        else:
            lis_num.append(lis_num[-1]+lis_num[-2])
        i += 1
    return lis_num

  方法5: 

def febonaci(n):
    def feb(i):
        if i<2:
            return i
        else:
            return feb(i-1)+feb(i-2)
    for i in range(n):
        print(feb(i))

 其中方法345可以直观的看到状态转移方程。

参考:Python 算法之 动态规划详解_XianZhe_的博客-CSDN博客_python 动态规划

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

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

相关文章

IT30--IT与业务业务与ITIT价值(3年之约已满)

从大学开始。。。 读大学前压根就没有见过计算机这个东西&#xff08;不得不感慨信息技术发展之快&#xff09;。可能因为高考数学考的还不错的原因&#xff0c;选择了计算机这个专业&#xff0c;后来研究生读的也是计算机的相关专业。当时班里的女生少&#xff0c;但没想到一…

java中多线程的基础知识

Process与Thread&#xff1a; 程序是指一段静态的代码,是指令和数据的有序集合,其本身没有任何运行的含义,它能够完成某些功能,它是应用软件执行的蓝本&#xff0c;它是一个静态的概念。 进程是关于某个数据集合的一次运行活动,它是操作系统动态执行的基本单元,也是程序的一次…

C++中二叉树的递归遍历方法2-2

在《C中二叉树的递归非遍历方法3-3》中提到&#xff0c;二叉树的层序遍历的输出顺序是从根节点开始&#xff0c;一层一层横向遍历各个节点。如图1所示的二叉树&#xff0c;层序遍历的输出的输出顺序为“1->2->3->4->5->6”。 图1 二叉树结构 1 递归实现层序遍历…

计算机视觉 基于CUDA编程的入门与实践 线程及同步一

一、并行执行规模 CUDA关于并行执行具有分层结构。每次内核启动时可以被切分成多个并行执行的块&#xff0c;而每个块又可以进一步地被切分成多个线程。这种并行执行的副本可以通过两种方式完成&#xff1a;一种是启动多个并行的块&#xff0c;每个块具有1个线程&#xff1b;另…

项目实战之旅游网(五)后台角色管理(下) 后台权限管理

目录 一.后台角色管理&#xff08;下&#xff09; 1.查询角色权限 2.修改角色权限 3.优化侧边栏菜单 二.后台权限管理 1.权限列表 2.新增权限 3.修改权限 4.删除权限 一.后台角色管理&#xff08;下&#xff09; 1.查询角色权限 先新建一个bean类型的实体类&#xf…

单商户商城系统功能拆解53—数据分析

单商户商城系统&#xff0c;也称为B2C自营电商模式单店商城系统。可以快速帮助个人、机构和企业搭建自己的私域交易线上商城。 单商户商城系统完美契合私域流量变现闭环交易使用。通常拥有丰富的营销玩法&#xff0c;例如拼团&#xff0c;秒杀&#xff0c;砍价&#xff0c;包邮…

一文清晰带你弄清楚Spring IOC 循环依赖问题是如何解决的

什么是循环依赖 循环依赖又被成为循环引用,即两个或者多个bean相互之间的持有对方,比如A 引用B,B引用C,C 又引用A,则它们最终反映为一个环,如下图所示: 循环依赖是对象之间的相互依赖关系,循环依赖就是一个死循环,除非有终结条件,否则就是死循环,最终导致内存溢出错误. 解决…

【Java 数据结构】优先级队列

篮球哥温馨提示&#xff1a;编程的同时不要忘记锻炼哦&#xff01;谁是你的优先级呢&#xff1f; 目录 1、优先级队列 1.1 优先级队列概念 1.2 堆的概念 1.3 堆的存储结构 2、模拟实现优先级队列 2.1 成员变量的设定 2.2 根据数组构造出一个堆 2.3 向下调整 2.4 creat…

电压放大器如何测试线性稳压器

有不少的电子工程师咨询电压放大器如何测试线性稳压器&#xff0c;那么这种要怎么做呢&#xff0c;下面让安泰电子来为大家介绍。 一、什么是低压差线性稳压器&#xff1f; 低压差线性稳压器是集成电路稳压器&#xff0c;经常用来电流主通道控制&#xff0c;芯片上集成导通电阻…

SQL 事务基础

事务基础 1 事务概念 所谓事务就是用户定义的一个数据库操作序列&#xff0c;这些操作要么全做&#xff0c;要不全不做&#xff0c;是一个不可分割的工作单位。 2 事务的特性&#xff08;ACID&#xff09; 原子性&#xff08;atomicity&#xff09; 事务是数据库工作的逻辑…

数据,信息,知识,智慧

数据&#xff0c;信息&#xff0c;知识&#xff0c;智慧 知识管理的对象有数据、信息、知识、智慧&#xff0c;而不仅仅是知识。将这些联系起来处理&#xff0c;就能期待综合效果。 作为知识资产的知识 传统的资源以人、物、钱为代表。但是&#xff0c;在经济活动的现场&…

2023年全国管理类联考英语二真题及解析

Section Ⅰ Use of English Here’s a common scenario that any number of entrepreneurs face today: you’re the CEO of a small business and though youre making a nice 1 , you need to find a way to take it to the next level. what you need to do is 2 growth by …

MobPush:社交app硝烟再起,如何突出重围?

推送&#xff0c;能够在产品和用户之间建立有效的连接。好的推送能够传达有价值的信息和提供好用的功能&#xff0c;让企业和用户沟通&#xff0c;把准确的信息第一时间传达。然而很多企业都没有意识到这一点&#xff0c;对于推送的频率&#xff0c;内容&#xff0c;以及针对各…

辗转相除法求最大公因数-C语言

辗转相除法&#xff0c;又名欧几里德算法&#xff0c;是求最大公约数的一种方法。以除数和余数反复做除法运算&#xff0c;最终当余数为0时&#xff0c;取当前算式除数为最大公约数。 例1&#xff1a;求2015和15的最大公因数。 2015 15 * 134 5 15 5 * 3 0 因此&#xff0…

亚马逊云科技 Build On - 咖啡厅Demo学习stepfunction serverless应用

荣幸参与和csdn和aws联合举办的buildon实验活动&#xff0c;主要目的还是学习stepfucntion的使用&#xff0c;这个服务能够集成大量aws service感觉可以出现很多有趣的用法。官方给出的文档已经非常详细了&#xff0c;这里只是对一些比较难理解的点进行了记录和解释&#xff0c…

restricted isometry property 稀疏 (CSDN_0002_20220908)

目录 1. 稀疏问题的引出 2. RIP 说明&#xff1a; 1. 由于参考多篇文献&#xff0c;所以本文的符号与原文略有不同。 2. 由于原文公式较多&#xff0c;所以本文采用了截图的形式&#xff0c;如需要电子版文档&#xff0c;可私信或留言。 1. 稀疏问题的引出 2. RIP 关于1-…

MySQL存储过程高级SQL语句总结

MySQL高级SQL语句&#xff08;存储过程&#xff09; 一、存储过程的概述 1.1 什么是存储过程 存储过程是一组为了完成特定功能的SQL语句集合。 存储过程在使用过程中是将常用或者复杂的工作预先使用SQL语句写好并用一个指定的名称存储起来&#xff0c;这个过程经编译和优化后…

Quarkus构建一个原生可执行文件

先决条件 大概15分钟 编辑器 安装GraalVM&#xff0c;并正确配置 Apache Maven 3.8.1 可以工作的容器 (Docker或者Podman) 一个 C语言工作开发环境 Quarkus应用程序代码 支持在C语言中进行原生编译 拥有一个C语言工作开发者环境意味着什么&#xff1f; 在Linux上&#xf…

华为手机恢复出厂设置后如何恢复数据

当您恢复出厂设置时&#xff0c;手机上存储的所有数据都会被清空。这是因为恢复出厂设置基本上是您从头开始设置手机的一种方式。 众所周知&#xff0c;重置手机会清除手机上的现有数据。如果这种强制删除让你丢失了重要数据&#xff0c;那么恢复出厂设置后数据还能恢复吗&…

企企通:如何利用数字化之道,赋能汽车行业供应链创新?

汽车是国民经济的支柱性企业&#xff0c;产业链长&#xff0c;涉及面广、带动性强&#xff0c;国际化程度高&#xff0c;在全球主要经济大国的产业体系中一直占据着重要地位。 我国汽车行业通过几十年的高速发展之后&#xff0c;从量变到质变&#xff0c;逐渐向低速增长的模式开…