动态规划

动态规划之最优化原理与动态规划方程 目录动态规划引言1 动态规划原理1.1 最短路问题及其解法1.2 动态规划的基本概念和术语1.3 最优化原理与动态规划方程1.3.1 最优化原理1.3.2 逆序动态规划方程1.3.3 顺序动态规划方程1.4 动态规划基本定理 动态规划 引言   1951年,美国数学家贝尔曼(R.Bellman)等根据一类所谓多阶段决策问题的特性,提出了解决这类问题的“最优化原理”,并研究了许多实际问题,从而创立了最优化的一个新分支----动态规划。   动态规划没有统一的数学模型,对不同的问题要采用不同的方法去建立它们的模 阅读详情

动态规划

一、简介

动态规划(dynamic programming)与分治方法很像,都是通过组合子问题的解来求解原问题。

分治方法将问题划分为互不相交的子问题,递归的求解子问题,再讲它们的解组合起来,求出原问题的解。

与之相反,动态规划应用于子问题重叠的情况,即不同的子问题具有公共的子子问题(子问题的求解是递归进行的,将其划分为更小的子子问题)。在这种情况下,分治算法会做许多不必要的工作,他会反复地求解那些公共子问题。而动态规划算法对每个子子问题只求解一次,将其解保存在一个表格中,从而无需每次求解一个子子问题时都重新计算,避免了这种不必要的计算工作。

动态规划解决的问题通常有两个特征:

1.最优化问题

2.子问题重叠

二、动态规划的几个例子
1、钢条切割

问题定义:给定一段长度为n英寸的钢条和一个价格表 pi(i=1,2,...,n) ,求切割钢条方案,使得销售收益 rn 最大。

价格表样例,每段长度为 i 英寸的钢条为公司带来pi美元的收益

钢条切割问题

使用普通的自顶向上的递归算法实现的解决思路如下:

//p是价格表,n是钢条长度
int cut_rod( int *p, int n )
{
    if ( n == 0 )
        return 0;
    int q = 0x80000000;     //先给q赋值一个尽可能小的值
    for ( int i = 1; i <= n; i++ )
    {
        q = max( q, p[i]+cut_rod( p, n-i ) );
    }
    return q;
}
int main( void )
{
    int p[] = { 0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30 };
    int result = memoized_cut_rod( p, 10 );
    cout << result << endl;
    return 0;
}

递归算法因为要对每一个子问题进行重复求解,所以在输入较大的n时,时间效率太低。

使用动态规划可以解决递归算法中对一个子问题进行重复求解而导致的低效率问题。解决的主要思路有:

1.带备忘的自顶向下:在递归过程中,每求得一个子问题的解,我们就将其保存下来,当下次需要求解一个子问题的解时,先检查这个子问题是否被保存过了。如果已经保存过了,则直接返回这个子问题的解。否则,再以递归的方式求解这个子问题的解。我们称这个递归过程是带备忘的,是因为它记住了之前已经计算过的结果。

2.自底向上法:因为任何子问题的求解都只依赖于“更小的”子问题的求解。因而我们可以将子问题按规模排序,按由小到大的顺序进行求解。当求解某个子问题时,它所依赖的那些更小的子问题都已求解完毕,结果已经保存。每个子问题只需求解一次,当我们求解它时,它的所有前提子问题都已经求解完成。

下面是带备忘的自顶向下解法:

int memoized_cut_rod_aux( int *p, int n, int *r )
{
    if ( r[n] >= 0 )
        return r[n];

    int q;
    if ( n == 0 )
        q = 0;
    else 
    {
        q = 0x80000000;
        for ( int i = 1; i <= n; i++ )
        {
            q = max( q, p[i]+memoized_cut_rod_aux( p, n-i, r ) );
        }
    }
    r[n] = q;
    return q;
}

int memoized_cut_rod( int *p, int n )
{
    int r[n+1];
    for ( int i = 0; i <= n; i++ )
    {
        r[i] = 0x80000000;
    }
    return memoized_cut_rod_aux( p, n, r );
}

下面是自顶向上版本的解法:

int bottom_up_cut_rod( int *p, int n )
{
    int r[n];
    r[0] = 0;
    int q;
    for ( int j = 1; j <= n; ++j )
    {
        q = 0x80000000;
        for ( int i = 1; i <= j; ++i )
        {
            q = max( q, p[i]+r[j-i] );
        }
        r[j] = q;
    }
    return r[n];
}
2、矩阵链乘法

矩阵链乘法问题可描述如下:给定n个矩阵的链 <A1,A2,....,An> ,矩阵 Ai 的规模为 Pi−1∗Pi(1<=i<=n) ,求完全括号化方案,使得计算乘积 A1A2...An 所需标量乘法次数最少。

分析:

1、刻画一个最优解的结构特征

为了构造一个矩阵链乘法问题实例的最优解,我们可以将问题划分为两个子问题( AiAi+1...Ak 和 Ak+1Ak+2...Aj 的最优括号化问题),求出子问题实例的最优解,然后将子问题的最优解组合起来。我们必须保证在确定分割点时,已经考察了所有可能的划分点,这样就可以保证不会遗漏最优解。

2、递归的定义最优解的值

用 m[i,j] 表示计算矩阵 Ai,j 所需标量乘法次数的最小值,原问题的最优解—计算 A1...n 所需的最低代价就是 m[1,n] 。可以得出求解原问题的递归求解公式为:

矩阵链乘法

3、运用动态规划的思想优化2中的递归方案,通常采用自底向上或者带备忘的自顶向下方法。

如果直接根据上面的公式写递归算法,时间效率上并不比暴力搜索的方法好,因为递归过程中子问题有重叠,所以我们要运用动态规划的思想优化递归方案。

(1)、自底向上表格法:

来自算法导论的伪代码:

MATRIX_CHAIN_ORDER(p)

n = p.length - 1
let m[1...n, 1...n] and s[1...n-1, 2...n] be new tables
for i = 1 to n
    m[i, i] = 0
for l = 2 to n
    for i = 1 to n-l+1
        j = i + 1 - l 
        m[i, j] = 0x07fffffff
        for k = i to j-1
        q = m[i, k] + m[k+1, j]+$p_{i-1}p_kp_j$
        if q < m[i, j]
            m[i, j] = q
            s[i, j] = k

说实话,不太能看懂,等到以后看懂了再写对应的c++代码。

3、最长公共子序列

最长公共子序列 问题即是给定两个序列 X=(x1,x2,...,xm) 和 Y=(y1,y2,...,yn) 求 X 和Y 长度最长的公共子序列。

​ 例如:X=BADCGE Y=BDRRCFE 则X和Y的最长公共子序列为BDCE.

1、刻画一个最优解的结构特征

设 X=(x1,x2,...,xn) 和 Y=(y1,y2,...,yn) 是两个序列,将X和Y的最长公共子序列记为LCS(X, Y).

找出LCS(X, Y)就是一个最优化问题。因为,我们需要找到X和Y中最长的那个公共子序列。而要找X和Y的LCS,首先考虑X的最后一个元素和Y的最后一个元素。

1) 如果 xn=ym ,即X的最后一个元素和Y的最后一个元素相同,这说明该元素一定位于公共子序列中,因此,现在只需要找: LCS(Xn−1,Ym−1)

2) 如果 xn!=ym ,那么它将产生两个子问题: LCS(Xn−1,Ym) 和 LCS(Xn,Ym−1)

因为序列X和序列Y的最后一个元素不相等,所以说明要么 xn ,要么 ym ,要么两个都 不是公共子序列中的一个元素。

LCS(Xn−1,Ym) 表示: (x1,x2,...,xn−1) 和 (y1,y2,...,yn) 的公共子序列。

LCS(Xn,Ym−1) 表示: (x1,x2,...,xn) 和 (y1,y2,...,yn−1) 的公共子序列。

求解上面两个子问题,得到的公共子序列谁最长,那谁就是 LCS(X,Y) 。用数学表示就是:

LCS(X,Y)=max(LCS(Xn,Ym−1),LCS(Xn,Ym−1))

所以,我们成功的将原问题转化为了三个规模更小的问题。

最小公共序列

2、LCS C++ 实现

enum { e_left_up = 10, e_up, e_left };

void print_LCS( int (*result)[7], char *strx, int xLen, int yLen )
{
    if ( xLen == 0 || yLen == 0 )
        return ;
    if ( result[xLen][yLen] == e_left_up )
    {
        print_LCS( result, strx, xLen-1, yLen-1 );
        printf( "%c", *strx );
    }
    else if ( result[xLen][yLen] == e_up )
    {
        print_LCS( result, strx, xLen-1, yLen );
    }
    else
    {
        print_LCS( result, strx, xLen, yLen-1 );
    }
}

int LCS( int (*result)[7], char *strx, char *stry )
{
    int row = strlen( strx ) + 1;
    int col = strlen( stry ) + 1;

    int c[row][col];

    for ( int i = 0; i < row; i++ )
    {
        c[i][0] = 0;
    }
    for ( int i = 0; i < col; i++ )
    {
        c[0][i] = 0;
    }

    for ( int i = 1; i < row; i++ )
    {
        for ( int j = 1; j < col; j++ )
        {
            if ( strx[i] == stry[j] )
            {
                c[i][j] = c[i-1][j-1] + 1;
                result[i][j] = e_left_up;
            }
            else if ( c[i-1][j] >= c[i][j-1] )
            {
                c[i][j] = c[i-1][j];
                result[i][j] = e_up;
            }
            else 
            {
                c[i][j] = c[i][j-1];
                result[i][j] = e_left;
            }
        }
    }
    return c[strlen(strx)][strlen(stry)];
}

参考文章:http://www.cnblogs.com/hapjin/p/5572483.html

【动态规划】不信看完你还不懂动态规划 1.什么是动态规划? 维基百科:动态规划(Dynamic programming,简称DP)是一种通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。 使用场景:动态规划常常适用于有重叠子问题和最优子结构性质的问题。 dynamic programming is a m·· ethod for solving a complex problem by breaking it down into a collection of simpler subproblems. 简单来说,动态规划其 阅读详情

相关推荐

详解动态规划

对每个i=1,2,...,n-1,首先将钢条切割为长度为i和n-i的两段,接着求解这两段的最优切割收益ri,rn-i(每种方案的最优收益为两段的最优收益之和),这就构成了求解原问题的一种方案。分治算法和动态规划都是将大问题划分成多个子问题,递归地求解子问题,再将它们的解组合起来,求出原问题的解。就是可选择列表是什么(求解问题的方案有多少种方案,最优解就是从n种方案中选择最优方案),其次才能从所有可能的选择中求出最值,这本身就是递归树的选择过程。要凑出的金额amount在选择的过程是动态变化的,它就是状态。

weixin_42083481的博客 1775

计算机算法:动态规划的概念、核心要素与经典问题(详细分析与总结)

动态规划方法通常用来求解最优化问题(optimization problem)。这类问题可以有很多可解,每个解都有一个值,我们希望寻找具有最优值(最小值或最大值)的解。我们称这样的解为问题的一个最优解(an optimal solution),而不是最优解(the optimal solution),因为可能有多个解都达到最优值。动态规划适用于子问题重叠的情况,也就是不同的子问题存在公共的子子问题。

乔卿的博客 2300

同花顺【红绿趋势】幅图指标 源码分析

a10:IF(差值<=0 ,0 ,差值*0.2 ,4 ,0),STICK,linethick5,colorred;a7:IF(差值<=0 ,0 ,差值*0.8 ,4 ,0),STICK,linethick5,colorred;a8:IF(差值<=0 ,0 ,差值*0.6 ,4 ,0),STICK,linethick5,colorred;a6:IF(差值<=0 ,0 ,差值*1 ,4 , 0),STICK,linethick5,colorred;DRAWICON(先锋<0,-25,1);

zhibiaogong的博客 4070

动态规划算法

动态规划 动态规划的性质: (1)最优化原理:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构,即满足最优化原理。 (2)无后效性:即某阶段状态(定义的新子问题)一旦确定,就不受这个状态以后决策的影响。也就是说,某状态以后的过程不会影响以前的状态,只与其以前的状态有关。 动态规划的步骤: (1)刻画一个最优解的结构特征 根据问题类型的规模和基本单位,把问题分为若干个阶段。在划分阶段时,注意确保子问题也是最优解,即通过剪贴法证明这个问题具有最优子结构(可以用动态规划解决问题)。 (2

weixin_46507363的博客 288

CPLD新手必看:安路EF2系列配置与烧录的避坑指南(含完整流程)

本文为CPLD新手提供了安路EF2系列芯片从硬件设计到软件烧录的完整避坑指南。重点解析了电源系统、时钟复位、JTAG接口等关键电路设计要点,并详细介绍了使用TD软件进行工程创建、代码编写、引脚分配及程序烧录的全流程,帮助开发者快速上手并规避常见问题。

weixin_29217235的博客 357

获取气体传感器温度调制响应数据并转换为NumPy数组

本任务旨在获取气体传感器在温度调制条件下的响应数据,将其处理为结构化数据格式(NumPy数组),以便用于机器学习模型训练。整个过程包含数据采集、预处理、特征工程和格式转换等关键步骤。

huanghm88的专栏 1207

算法学习—动态规划

动态规划(dynamic programming)是通过组合子问题来求解原问题的方法,它倾向于解决子问题重叠的情况,即不同子问题具有公共的子问题。 从这方面来看,动态规划都可以用递归来实现,但是递归是从上到下的思路进行处理的,也就是说递归是从完整的问题,逐次向子问题求解的过程,但是动态规划却是从规模最小的子问题开始,向上逐步求解,求解过程中保存这些小规模的子问题作为求解大问题的依据,并最终求出结果。例如求解斐波那契数列,使用递归的思路是从f(n)依次向下求解f(n-1)和f(n-2),但是使用动态规划的思路

teaandnoodle的专栏 1890

ThinkpadCPU锁频0.4G问题

这篇帖子总结的很好,有这种问题可以试一试:但是切记,不要病急乱投医,冷静下来,慢慢分析和排除故障,有时候,并不需要我们知道所有的原理,只要问题解决了就是OK的。ThinkpadCPU锁频0.4G,具体是过程是今天我需要去楼下打印东西,要带着笔记本电脑,拔掉电源我就去楼下。一般这种问题很有可能是电源导致的,先不要病急乱投医,刷BIOS,装系统什么的,没用。但是确实解决了我的问题,记录下来。带着电脑回到工位,插上电源。突然我突发奇想,拔掉电源,神奇的事情发生了,CPU频率复活了,再插上电源,CPU完全恢复了。

小幽余生不加糖 1万+

算法 - 动态规划

动态规划把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解

AlvinTech14的专栏 1041

Windows安装WSL子系统及docker,以及WSL和docker配置、使用及问题解决

在Windows操作系统中,Ubuntu子系统(也称为Windows Subsystem for Linux, WSL)为开发者提供了一个在Windows环境下运行Linux环境的平台。然而,有时用户在按照Ubuntu子系统或者使用WSL时,可能会遇到各种问题,下面总结一下解决方式。想要在Windows上安装Docker(实际上是基于Hyper-V或者WSL2这两项虚拟化技术),需要开启虚拟化功能,所以不管是对于系统还是硬件都有一定的要求。

sym的博客 9788

YOLOv8改进 | 特殊场景检测篇 | 最新的多尺度特征提取DICAM(全网独家首发,增强水下图像的质量)

本文给大家带来的最新改进机制是多尺度特征提取和通道注意力机制DICAM,深度Inception和通道注意力模块(DICAM)主要用于用于增强水下图像的质量、对比度和色偏。所提出的DICAM模型考虑了水下图像的比例退化和不均匀色偏,从而提高图像的质量。通过在两个公开的水下图像增强数据集上的广泛实验,验证了提出的模型在全参考和无参考图像质量评估指标方面。欢迎大家订阅我的专栏一起学习YOLO,购买专栏读者联系读者入群获取进阶项目文件!

Snu77的博客 2216

第三章 动态规划

学习要点理解动态规划的概念 掌握动态规划算法的基本要素 (1) 最优子结构性质 (2) 重复子问题性质 掌握设计动态规划算法的步骤 (1) 找出最优解的性质,并刻画其结构特征 (2) 递归地定义最优值 (3) 以自底向上的方式计算最优解 (4) 根据计算最优值时得到的信息构造最优解。动态规划与分治法类似,都是将原问题划分成若干子问题求解,不同的是,适用于动态规划法解的问题,经分解得到

haonanren2bu2的专栏 782

RK3588,V4l2 读取Gmsl相机, Rga yuv422转换rgb (dma), 实现零拷贝

RK3588, 使用V4l2 读取 gmsl 相机,获得yuv422格式图像, 使用 rga 转换 rgb 图像。减少cpu占用率. 内存管理方式采用 dma,实现零拷贝.

J。 1263

动态规划常见类型总结

本文针对动态规划的常见类型进行总结。虽说总结的是动态规划,但顺便把递推也放了进来。严格来说,递推不属于动态规划问题,因为动态规划不仅有递推过程,还要有决策(即取最优),但广义的动态规划是可以包含递推的,递推是一类简单的、特殊的动态规划,毕竟动态规划与递推密不可分。动态规划类型主要分为纯粹动态规划问题和复合动态规划问题。 几点说明: 1、博主本人于2012年对信息学竞赛中的动态规划问题进行了总结...

FanJin的博客 2万+

78.在 Vue3 中使用 OpenLayers 实现地图地点搜索定位功能

本文详细介绍了如何在 Vue3 中集成 OpenLayers,实现地图地点搜索和定位功能。Vue3 项目环境的搭建与依赖安装。使用语法实现地图初始化和控件集成。通过 OpenLayers 的 Popup 和 Geocoder 插件,实现地址搜索和定位。希望这篇博文能帮助你快速掌握 Vue3 与 OpenLayers 的集成技术。如果在使用过程中遇到问题,欢迎在评论区留言讨论,或者参考 OpenLayers 官方文档获得更多帮助。注意。

小彭的博客 1854

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

为什么你学不过动态规划?告别动态规划,谈谈我的经验

动态规划难吗?说实话,我觉得很难,特别是对于初学者来说,我当时入门动态规划的时候,是看 0-1 背包问题,当时真的是一脸懵逼。后来,我遇到动态规划的题,看的懂答案,但就是自己不会做,不知道怎么下手。就像做递归的题,看的懂答案,但下不了手,关于递归的,我之前也写过一篇套路的文章,如果对递归不大懂的,强烈建议看一看:为什么你学不会递归,告别递归,谈谈我的经验 对于动态规划,春招秋招时好多题都会用到动态...

帅地 3万+

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

算法之动态规划

目录什么是动态规划 概念动态规划的特点动态规划的写法适用的场景何时使用动态规划核心套路区别 斐波那契理解动态规划 换零钱问题 区别 分治和动态规划 贪心和动态规划

一名在校大三学习JAVA 9705

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

C++之动态规划(动态规划入门)

好

m0_62755690的博客 8506

『动态规划』动态规划概述

1.动态规划创始人2.定义3.总体思想4.基本要素最优子结构重叠子问题5.备忘录法(记忆化搜索)6.斐波那契数列(备忘录法)7.数字三角形经典递归解法记忆化搜索(备忘录法)动态规划法(T(n)=O(n^2^))动态规划是将多阶段决策问题进行公式化的一种技术,它是运筹学的一个分支, 用于求解多阶段决策过程的最优化问题动态规划方程又称为贝尔曼方程。...

一个专注于客户端开发的技术er,不定期更新Android,Flutter,HormonyOS等方向的使用心得和感悟 2680

《动态规划》— 动态规划分类

动态规划(英语:Dynamic programming,DP)是一种在数学、计算机科学和经济学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。 动态规划常常适用于有重叠子问题和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。 动态规划背后的基本思想非常简单。大致上,若要解一个给定问题,我们需要解其不同部分(即子问题),再合并子问题的解以得出原问题的解。 通常许...

69小石头的博客 1367

什么是动态规划?

什么是动态规划? 动态规划(Dynamic Programming)是一种分阶段求解决策问题的数学思想,它通过把原问题分解为简单的子问题来解决复杂问题.动态规划在很多领域都有着广泛的应用,例如管理学,经济学,数学,生物学. 动态规划适用于解决带有最优子结构和子问题重叠性质的问题. 最优子结构: 即是局部最优解能够决定全局最优解(也可以认为是问题可以被分解为子问题来解决),如果问题的最...

u010412301的博客 9622

MATLAB 动态规划

动态规划是一种数学优化方法,它是一种在给定约束条件下,求解最优化问题的方法。动态规划的基本思想是将原问题分解为若干个子问题,先求解子问题的最优解,然后根据子问题的最优解,求解原问题的最优解。将原问题分解为子问题确定状态确定一些初始状态(边界状态)的值确定状态转移方程思想上类似于递归,但动态规划采用记录子问题的最优解的方法,避免了重复计算子问题的最优解,从而提高了计算效率;除此之外,动态规划通常采用自底向上的方法,而递归通常采用自顶向下的方法。

小嗷犬的博客 5042

动态规划专题(一维动态规划)

算法联系

qq_63523553的博客 1500

什么是动态规划(Dynamic Programming)?动态规划的意义是什么?

希望本文不仅能告诉你什么是动态规划,也能给你一种如何分析、求解动态规划问题的思考方式。0001b 动态规划介绍运筹学中的动态规划动态规划(Dynamic Programming,简称DP)是运筹学的一个分支,它是解决多阶段决策过程最优化的一种数学方法。把多阶段问题变换为一系列相互联系的的单阶段问题,然后逐个加以解决。这里提到动态规划其实是一种数学方法,是求解某类问题的一种方法,而不是一种特殊的算法,没有一个标准的数学表达式或明确定义的一种规则。比如我们接触过的”排序算法“,”二叉树遍历算法“等,这些算法都是

weixin_44145478的博客 4802
上一篇: linux命令集合
下一篇: 网络基础常考面试题
Findway_
博客等级 码龄10年 36粉丝 117原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值