动态规划算法与典型例题

2023-11-11

目录

前言

一、动态规划要素(条件)

二、动态规划算法设计步骤

三、复杂度分析

四、典型例题1——游艇租聘

五、典型例题2——0-1背包问题

六、典型例题3——跳台阶问题

七、典型例题4——强盗抢劫问题

总结


前言

        动态规划也是一种分治思想,分治算法是把原问题分解为若干子问题,自顶向下求解子问题,合并子问题的解,从而得到原问题的解。动态规划是把原问题分解为若干子问题,自底向上,先求解子问题,把结果存储在表格中,在求解大问题时直接从表格中查询小问题的解,避免重复计算,从而提高算法效率。


一、动态规划要素(条件)

        1.最优子结构,问题的最优解包括子问题的最优解。如果不具有最优子结构则不能使用动态规划。

        2.子问题重叠,在求解子问题时有大量子问题是重复的,那么只需求解一次,然后把它存储到表格中,以后使用时直接查询,不需重复求解。子问题重叠不是使用动态规划的必要条件,但是只有存在子问题重叠才能彰显动态规划的优势。线

二、动态规划算法设计步骤

        1.分析最优解的结构特征

        2.建立最优值递归式

        3.自底向上计算最优值,并记录

        4.构造最优解

        很多复杂的问题很难找到递归式,但是一旦找到递归式,那么算法已经实现99%。

三、复杂度分析

        时间复杂度:一般为O(n), O(n^2), O(n^3)等n的整数方,看其需要几重循环。

        空间复杂度:一般为O(1),O(n), O(n*m)等,看其子问题最优解与几个控制量有关。

四、典型例题1——游艇租聘

        问题描述:长江游艇俱乐部在长江上设置了n个游艇租聘站,游客可以在这些租聘站租用游艇,然后在下游的任何一个租聘站归还。游艇出租站i到j的租金为r(i, j),1 <=  i< j<= n,设计一个算法,计算从出租站i到j所需的最少租金。

        构造二维数组m[i][j]表示从出租站i到j的最少租金,那么两个子问题:(i, i+1, ... , k), (k, k+1, ..., j)最优值分别是m[i][k]和m[k][j]。

递归式:

m[i][j]=\left\{\begin{matrix} 0 & ,j=i \\ r[i][j] &,j=i+1 \\ min \begin{Bmatrix} m[i][k]+m[k][j], r[i][j] \end{Bmatrix}& ,j > i+1 , i < k < j \end{matrix}\right.

伪代码:

void rent()
{
    int i, j, k, d;
    for(d = 3, d <= n; ++d)//将问题分为小规模d。d=0时,租金为0;d=1时,租金为单站租金
    {
        for(i = 1; i <= n-d+1; ++i)//起点
        {
            j = i+d-1;//终点
            for(k = i+1; k < i+d-1; ++k)//换乘站,求解每一小规模子问题的解
            {
                int temp = m[i][k] + m[k][j];
                if(temp < m[i][j]) m[i][j] = temp;
            }
        }
    }
}

        总体的求解过程为沿着主对角线一层一层向上,直到右上角填充完毕,则右上角值为所求解。

        时间复杂度O(n^3),空间复杂度O(n^2)。如果在原数组上更新计算值,则空间复杂度可以优化到O(1)。

五、典型例题2——0-1背包问题

        问题描述:动态规划针对不可切割物品,可切割物品可以使用贪心算法。

        约束条件:

\left\{\begin{matrix} \sum w_i*x_i \leqslant W&,1 \leqslant i \leqslant n \\ x_i\in \begin{Bmatrix} 0,1 \end{Bmatrix}& ,1 \leqslant i \leqslant n \end{matrix}\right.

        目标函数:

max\sum v_i*x_i, 1 \leqslant i \leqslant n

        c[i][j]表示前i件物品放入容量为j的购物车可以获得的最大价值。

        递归式:

c[i][j]=\left\{\begin{matrix} c[i-1][j] &, j<w_i \\ max\begin{Bmatrix} c[i-1][j], c[i-1][j-w[i]]+v[i] \end{Bmatrix}& ,j\geqslant w_i \end{matrix}\right.

for(int i = 1; i <= n; ++i)
{
    for(int j = 1; j <= w; ++j)
    {
        if(j < w[i])//i物品重量大于购物车,则不放入
        {
            c[i][j] = c[i-1][j];
        }else{//比较i物品放入后能否让购物车价值最大
            c[i][j] = max(c[i-1][j], c[i-1][j-w[i]]+v[i]);
        }
    }
}

        总体求解过程一层一层求解,右下角为所求解。

        时间复杂度O(n*W),空间复杂度O(n*W)。

六、典型例题3——跳台阶问题

        问题描述:有 N 阶楼梯,每次可上一阶或两阶,求有多少种上楼梯的方法。

        容易证明该递推式是斐波拉切数列,

f(n) = n, n < 3

f(n)=f(n-1)+f(n-2), n\geqslant 3

        代码:

int jump(int n)
{
    if(n < 3) return n;
    int i = 1, j = 2, res = 0;
    for(int k = 0; k < n-2; ++k)
    {
        res = i + j;
        i = j;
        j = res;
    }
    return res;
}

        时间复杂度O(n),空间复杂度O(1)。

七、典型例题4——强盗抢劫问题

        问题描述:强盗抢劫一排房间,每个房间都有钱,不能抢劫两个相邻的房间,要求抢的钱最多。

        一维数组dp[i]是当抢到第i个数时,能抢到最大值,从局部最大值推到最终结果最大。

        递归式:

DP[i] = max(DP[i-2] + nums [ i ], DP[i-1])

        代码:

int robber(vector<int> &nums)
{
    int size = nums.size();
    if(size == 0) return 0;
    if(size == 1) return nums[0];

    vector<int> dp(size, 0);
    dp[0] = nums[0];
    dp[1] = nums[0] > nums[1] ? nums[0] : nums[1];
    
    for(int i = 2; i < size; ++i)
    {
        dp[i] = max(dp[i-2] + nums[i], dp[i-1]);
    }
    return dp[size-1];
}

        时间复杂度O(n),空间复杂度O(n)。


总结

        动态规划最大的优势在可以利用已知得出未知,求解过程中最重要且最困难的是要找出状态转移方程(递推式),同时还需要注意边界条件的设置。上述的经典问题解题思路具有较大参考价值。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

动态规划算法与典型例题 的相关文章

随机推荐

  • 【C++简明教程】Python和C++指定元素排序比较

    Python 中的排序 在 Python 中 常用的排序就是 sorted 对于列表这种数据结构来说 还有 sort 方法 列表的排序 使用 sort 方法进行排序 以第二个值进行升序排序 列表的 sort 方法是原地排序 另外一种排序方法
  • CMake的使用--以ORCA避碰C++库为例

    1 安装cmake 链接 Download CMake 版本需下载Binary distributions这个模块下的 Windows x64 Installer cmake 3 27 1 windows x86 64 msi 注意事项 1
  • CentOS6.5 安装 抓包工具tcpdump

    1 裸机没装GCC 离线安装 首先到http vault centos org 6 5 os x86 64 Packages 下载用到的rpm包 包括 ppl 0 10 2 11 el6 x86 64 rpm cloog ppl 0 15
  • LabVIEW自带函数Database Toolkit实现SQL Server操作(上)

    目录 一 函数位置 二 函数一览 三 主要介绍 1 DB Tool Open Connection vi 2 DBTool Close Connection vi 3 Database Variant To Data vi 4 DBTool
  • 浅析Redux 的 store enhancer

    相信大家都知道Redux的middleware 中间件 的概念 Redux通过middleware可以完成发送异步action 网络请求 打印action的日志等功能 相对而言 Redux的store enhancer的概念 很多人并不是很
  • 【MLOps】第 5 章 : 生产准备

    大家好 我是Sonhhxg 柒 希望你看完之后 能对你有所帮助 不足请指正 共同学习交流 个人主页 Sonhhxg 柒的博客 CSDN博客 欢迎各位 点赞 收藏 留言 系列专栏 机器学习 ML 自然语言处理 NLP 深度学习 DL fore
  • 副本与ISR设计--Kafka从入门到精通(十四)

    上篇文章说了 broker的消息设计 采用紧凑的byteBuffer 存储设计主要包含attribute后三个表示压缩类型 还有crc效验 以及key和value 后面新增了时间戳 Broker消息设计 Kafka从入门到精通 十三 htt
  • js实现数学的排列组合

    js实现数学的排列组合 实现 组合 param arr 待选数组 param size 从数组里面要抽几个元素进行组合 function combination arr size 1 45 3 9 4 14 1 const r param
  • 如何二次封装Element-Plus table组件

    最近做了一个后台的项目 需要用到大量的表格组件 我就试着把它给封装了一下 记录一下 那么现在开始了 父页面代码
  • Linux_centos7_网络管理1_2

    测试网络连接状态 kingarthur localhost ping www google com PING www google com 174 37 175 229 56 84 bytes of data C www google co
  • nginx_upstream_check_module模块

    nginx upstream check module模块 一个更专业的模块 来专门提供负载均衡器内节点的健康检查的 这个就是淘宝技术团队开发的 nginx 模块nginx upstream check module 通过它可以用来检测后端
  • 静态链接和动态链接的区别

    在理解静态和动态 共享 库链接之间的区别之前 让我们先看一个典型程序的生命周期 从编写源代码到执行它 首先使用任何程序员选择的编辑器以文本文件的形式编写程序 然后必须对其进行编译以将文本文件转换为机器可以理解和执行的目标代码 通常我们编写的
  • 1216项目设计模板

    一 基本信息 目标上线时间 yyyy mm dd 项目人员 研发 测试 背景 二 功能需求 1 业务平台 1 业务的订购 配置默认的模板或者策略 外链图片转存失败 源站可能有防盗链机制 建议将图片保存下来直接上传 img I8vhSe47
  • 最全的Pandas 日期处理 超强总结!

    对于 Pandas 来说 可以处理众多的数据类型 其中最有趣和最重要的数据类型之一就是时间序列数据 时间序列数据无处不在 它在各个行业都有很多应用 患者健康指标 股票价格变化 天气记录 经济指标 服务器 网络 传感器和应用程序性能监控都是时
  • leetcode-135-分发糖果

    老师想给孩子们分发糖果 有 N 个孩子站成了一条直线 老师会根据每个孩子的表现 预先给他们评分 你需要按照以下要求 帮助老师给这些孩子分发糖果 每个孩子至少分配到 1 个糖果 相邻的孩子中 评分高的孩子必须获得更多的糖果 那么这样下来 老师
  • SpringBoot 集成sharding-jdbc 提示:Failed to configure a DataSource: ‘url‘ attribute is not specified ***

    问题描述 今天使用SpringBoot 集成sharding jdbc 4 1 1实现分库分表时报错 APPLICATION FAILED TO START Description Failed to configure a DataSou
  • 记录一次因now()函数应用周期性查不到数据的问题

    问题原因 查询sql使用了now 函数 测试环境数据库所在的容器日期不对 与实际时间晚8个小时 问题背景描述 某天下午快要下班的时候 大概五点的样子 某个测试小哥在系统里点击用户注册功能注册后 一切数据都正常生成后 登录新注册的用户 发现这
  • 基础算法题——Radio Transmission(KMP-next 妙用)

    Radio Transmission 解题思路 在KMP算法中 next l 记录的就是字符串最长的相同的前缀与后缀 也就是说在题目字符串中有一段字符串是重复出现的 那么减去重复出现的字符串以后 剩下的就是这个字符串最小的循环节 比较字符串
  • 19.RV1126_RV1109编写并移植nvp6021驱动

    文章目录 前言 确定硬件 配置设备树生成节点 前言 nvp6021是一个i2C器件 因此 应该编写I2C设备驱动 既然是I2C设备驱动 应该确定的有 使用的是哪一路I2C I2C设备地址是多少等 确定硬件 使用的是哪一路I2C 从上面可以看
  • 动态规划算法与典型例题

    目录 前言 一 动态规划要素 条件 二 动态规划算法设计步骤 三 复杂度分析 四 典型例题1 游艇租聘 五 典型例题2 0 1背包问题 六 典型例题3 跳台阶问题 七 典型例题4 强盗抢劫问题 总结 前言 动态规划也是一种分治思想 分治算法