CSP-J/S复赛算法 动态规划初步

news2024/11/26 11:46:58

文章目录

  • 前言
  • 动态规划
  • 动态规划常见形式
    • 动态规划求最值的几个例子
      • 1. **背包问题**
      • 2. **最短路径问题**
      • 3. **最小硬币找零问题**
      • 4. **最长递增子序列**
    • 总结
  • 最优子结构
    • 举个简单的例子
    • 其他例子
    • 条件
  • DP的核心就是穷举
      • 具体解释
  • 递归的算法时间复杂度
  • dp数组的迭代解法
    • 通俗易懂的解释
    • 比喻
  • 状态转移方程详解
    • 状态转移方程中的状态概念
      • 通俗易懂的解释:
      • 举个例子:
      • 状态总结:
  • DP的无后效性
    • 通俗易懂的解释
    • 举个例子
    • 特点总结
    • 例子
  • DP的本质
    • 动态规划(DP)为什么快?
    • 通俗解释
    • 动态规划的核心是什么?
    • 如何设计DP算法
      • 1. **我是谁?(设计状态)**
      • 2. **我从哪里来?(状态表示:f(x))**
      • 3. **我要到哪里去?(设计状态转移)**
      • 设计 DP 算法的一般步骤:
      • 举个例子:
  • 总结


前言


动态规划

动态规划(Dynamic Programming)其实是一个很聪明的“拆问题”的方法。我们常常会遇到一些很大的问题,比如要做很多选择,走很多步才能完成。动态规划就是把这些问题一步步拆成小问题来解决,每次解决小问题的时候,都记住这个问题的答案,以后如果再遇到这个问题,就不用重新计算了,直接用之前的答案。

动态规划常见形式

动态规划的一个常见形式就是求最值,也就是在一系列选择中找到最优解(比如最大值或最小值)。问题可以是找最短路径、最大利润、最少步骤等等。动态规划的核心思想是通过把大问题分解成小问题,然后一步步解决小问题,最终找到整个问题的最优解。

动态规划求最值的几个例子

1. 背包问题

想象你有一个背包,能装有限的重量,同时有许多物品,每个物品有不同的重量和价值。你想装入背包的物品总价值最大,但又不能超过背包的承重。动态规划可以帮助你在选择哪些物品时,找到一个最优方案,使背包内物品的总价值最高。

2. 最短路径问题

给定一张地图,其中每条路都有一定的长度,问从起点到终点的最短距离是多少。动态规划的思路是每次选择一条最短的路,并通过递推的方式一步步缩短问题规模,最终找到从起点到终点的最短路径。

3. 最小硬币找零问题

假设你有不同面值的硬币,现在需要找一定金额的零钱,问你最少需要多少个硬币。动态规划的思路是每次都考虑使用一枚硬币,然后递归地计算剩下的金额最少需要多少硬币,通过这样的递推方式,找到找零所需的最少硬币数量。

4. 最长递增子序列

给定一个数字序列,找出其中最长的递增子序列(子序列中的数字是递增的)。动态规划的思路是从头到尾扫描数组,每次都记录以当前数字为结尾的最长递增子序列长度,最终找到全局的最长递增子序列。

总结

动态规划通常用来解决那些“从多个选择中找到最优解”的问题,比如找最大值、最小值、最长路径、最短路径等。通过把问题一步步分解并保存中间结果,动态规划能让我们高效地解决这些问题。

最优子结构

最优子结构是动态规划的核心概念之一,它指的是一个问题的最优解可以通过其子问题的最优解来构造出来。换句话说,就是大问题的最优解由若干个小问题的最优解组成。

举个简单的例子

假设我们要从城市A到城市C,途中会经过城市B。我们想知道如何从A到C的最短路径。那么,如果我们知道从A到B的最短路径,再加上从B到C的最短路径,就可以得到从A到C的最短路径。这就是最优子结构的体现:从A到C的最优解可以通过两个子问题(A到B和B到C)的最优解得到。

其他例子

  1. 背包问题
    在背包问题中,假设我们已经解决了重量为W的背包的最优解(最大价值),那么如果再给定一个物品,我们可以通过比较“放这个物品”和“不放这个物品”的两种情况,来决定最终的最优解。这里,每个背包容量的最优解都依赖于容量更小的背包的最优解。

  2. 斐波那契数列
    计算斐波那契数列时,某个位置的值是前两个位置值的和, F ( n ) = F ( n − 1 ) + F ( n − 2 ) F(n) = F(n-1) + F(n-2) F(n)=F(n1)+F(n2)。每个位置的最优解(即数值)依赖于它前面两个子问题的最优解。

条件

要满足最优子结构,问题必须具有以下两个特征:

  1. 重叠子问题:大问题可以分解成重复的小问题。
  2. 子问题独立性:每个子问题的解都是独立的,不受其他子问题解的影响。

如果一个问题具备最优子结构,就可以用动态规划来高效地求解。

DP的核心就是穷举

DP的核心是穷举。这意味着在动态规划(DP)中,解决问题的关键步骤就是穷举所有可能的解法,然后通过一些技巧来优化穷举过程

具体解释

  1. 穷举存在“重叠子问题”

    • 许多问题在求解时会遇到相同的子问题多次重复出现。如果不加优化,每次都要重新计算相同的子问题,导致时间浪费。
    • 动态规划的一个优化思路就是通过“备忘录”或“DP Table”的方式记录这些已经计算过的子问题结果,避免重复计算,从而提高效率。
  2. 具备最优子结构

    • 这是动态规划的另一个核心思想。如果一个问题的最优解可以通过它的子问题的最优解来得到,那就具备了最优子结构的性质。基于这一性质,动态规划通过递推或者递归的方式一步步求解子问题,最终获得问题的最优解。
  3. 状态转移方程

    • 状态转移方程是解决动态规划问题的关键之一。它描述了如何从一个状态转移到另一个状态,并通过合适的方式找到最优解。简而言之,状态转移方程规定了如何根据前面已知的状态推导出当前状态的解。

总结:
动态规划的核心就是通过穷举所有可能的方案,并结合备忘录来优化重叠的子问题,同时依靠最优子结构状态转移方程来一步步构建最优解。

递归的算法时间复杂度

就是其子问题个数*子问题所需要的时间

dp数组的迭代解法

当我们在解决问题时,如果把已经算过的答案记下来,就可以避免重复计算,从而更快地找到答案。这个记录答案的地方叫做DP表,就像是一张我们专门用来记答案的表格。

通俗易懂的解释

  • 备忘录就像做作业时,我们把每一步的答案写在纸上。以后如果再遇到相同的问题,就可以直接看之前写下的答案,而不用再重新算一次。

  • DP表(动态规划表)就是这张专门的“纸”,我们会把每一步的答案都写在上面。这样,当我们需要计算后面的答案时,就可以根据前面写下的答案一步步推算出来,而不是每次从头开始。

  • 自底向上推算的意思是,我们从最简单的、最小的问题开始解决,逐步解决更复杂的问题,就像搭积木一样,先搭好底部,再往上叠。

这就是「递推」的思路
这也是动态规划一般都脱离了递归,而是由循环迭代完成计算的原因

比喻

想象你在解一个迷宫,每走一步都记下路径。下一次走到同样的地方,你就可以看看之前的记录,直接走对的路,不用再迷路。这就是DP表的作用,把已经走过的路(答案)记下来,后面遇到类似的问题就可以轻松解决。

状态转移方程详解

在DP中,最重要的就是状态转移方程,它就类似于递归中的递推方程
所以我们需要详细来学它

状态转移方程中的状态概念

在动态规划的状态转移方程中,状态指的是问题在某个步骤或者某个阶段下的一个“局部解”或“情况”。每个状态代表了问题在特定条件下的当前结果。

通俗易懂的解释:

假设我们在玩一个游戏,每一步都可能会遇到不同的情况,这些“情况”就是状态。根据当前状态,你会选择不同的策略,然后转移到下一步,也就是下一个状态。

举个例子:

假设你要爬楼梯,总共有5级台阶,你每次可以选择迈1步或2步。

  • 状态就是你现在站在哪一级台阶上。例如,你站在第3级台阶时,这就是一种状态。
  • 你的状态转移可能是:如果你选择迈1步,你会到达第4级台阶;如果你选择迈2步,你就会到第5级台阶。这就是从第3级台阶(当前状态)到第4级或第5级台阶(下一个状态)的转移过程。

状态总结:

  1. 状态描述了问题的当前情况或阶段(比如爬到某一级台阶上)。
  2. 在每个状态下,都会根据某种规则转移到下一个状态(比如走一步或走两步)。
  3. 最终的目标就是从初始状态逐步转移到目标状态(比如从第0级台阶到第5级台阶)。

在动态规划中,状态就是问题的每个阶段的描述。通过找到状态间的关系(状态转移方程),我们就能一步步求解问题。

DP的无后效性

DP的无后效性,简单来说,就是在动态规划中,当前状态的选择和结果只依赖于之前的状态,而不会受到更早之前的状态影响。也就是说,过去的决策一旦做出,就不会影响后续的状态转移。

通俗易懂的解释

无后效性就像是你做一道数学题,每一步的答案只需要看你前一步的结果,不需要再回头看更早的步骤。只要你知道了上一步的结果,就可以推算出下一步,不用管更前面的细节。

举个例子

假设你在走迷宫,你每一步的方向选择只取决于你现在站在哪个路口,不会因为你从哪个路口走到这里而影响接下来的选择。只要知道当前的位置,你就能决定下一步怎么走,不需要回顾整个走过的路径。

特点总结

  • 只看当前,不看过去:当前的状态转移只取决于前一个状态,而不会回头依赖更早的状态。
  • 每一步决策独立:当前状态的决策不会受到过去的具体路径影响,只要前一步的结果是正确的,就能继续往前推算。

例子

比如你在计算爬楼梯的方式:

  • 如果你站在第3级台阶上,你的下一步可以选择迈1步到第4级,或者迈2步到第5级。
  • 这时,你的选择只依赖于当前第3级台阶,而不需要回顾你之前是从第1级台阶还是第2级台阶到的第3级

无后效性是动态规划的核心之一,它保证了我们可以通过递推、一步步从前向后计算每个状态,而不用担心更早的状态对结果的影响。

DP的本质

动态规划(DP)为什么快?

动态规划之所以快,是因为它解决了重叠子问题。通过记录(缓存)已经计算过的子问题结果,避免重复计算,从而大大提高了效率。这种记录的方式叫做备忘录DP表。动态规划通过这些优化,使得原本指数级的复杂度问题可以降低到多项式级别,大大加快了求解速度。

通俗解释

假设你在爬山,每次爬到某个高度,你会把这个高度的路线记录下来。下次再到这个高度时,就不用再重新走一遍所有可能的路线,只需要直接看之前记下的路线就可以继续往前走。这样省去了重复走老路的时间和精力,整体速度就快了很多。

动态规划的核心是什么?

动态规划的核心是穷举,但它通过记忆化状态转移来减少重复计算,从而使得穷举变得可行和高效。核心概念包括:

  1. 重叠子问题:问题可以被分解成多个重复的小问题,解决一次就不需要再解决第二次。DP通过记忆(比如用表格记录)已经解决的子问题,避免重复计算。

  2. 最优子结构:当前问题的最优解可以通过子问题的最优解来构造,这意味着我们可以一步步构建出整个问题的最优解。

  3. 状态转移方程:这是描述如何从一个状态转移到另一个状态的公式,它是动态规划的核心步骤,指导如何从已知解推导出未知解。

设计动态规划(DP)算法通常可以分为几个关键步骤,每个步骤都帮助我们一步步明确如何通过状态转移来求解问题。根据你上传的图片,可以简化为几个核心问题:

如何设计DP算法

1. 我是谁?(设计状态)

  • 状态代表了问题在某一个时刻或某一局部的情况,通常用一个变量或一组变量来描述。
  • 你需要明确在这个问题的解法中,每一个状态要代表什么,例如当前已经完成了哪些任务或已经走到了哪一步。

2. 我从哪里来?(状态表示:f(x))

  • 这里是设计递推关系,定义如何从之前的状态推导出当前状态的值。
  • 也就是状态转移方程,它告诉我们如何从小规模的问题一步步推导到大规模的解。例如,在求解某个问题时,当前状态可能是由前一个状态或几个前面的状态决定的。

3. 我要到哪里去?(设计状态转移)

  • 这一步要明确最终的目标,也就是最优解的状态是什么。通常是你要求解的问题的最优答案或者目标状态,比如走到终点、获得最大收益等。

设计 DP 算法的一般步骤:

  1. 定义状态:明确问题的每一步局部的情况,用状态表示出来。
  2. 确定状态转移方程:找出如何通过子问题的解来推导出当前状态的解。
  3. 设定边界条件:初始化一些最基础的状态,也就是边界条件。
  4. 最终解:找到你要的最终目标,这个目标通常是状态中的一个解。

举个例子:

假设我们要求一个阶梯问题,问你走到第 (n) 级台阶有多少种走法,规则是每次你可以选择走 1 级或 2 级。

  • 设计状态:令 (f(n)) 表示到达第 (n) 级台阶的走法总数。
  • 状态转移方程:你可以从第 (n-1) 级台阶走一步到 (n),也可以从第 (n-2) 级台阶走两步到 (n)。因此,状态转移方程是:
    f ( n ) = f ( n − 1 ) + f ( n − 2 ) f(n) = f(n-1) + f(n-2) f(n)=f(n1)+f(n2)
  • 边界条件:第 0 级台阶(地面)只有一种走法,站在那里不动,因此 (f(0) = 1),而第 1 级台阶只有一种走法,从第 0 级走一步,(f(1) = 1)。
  • 最终解:目标是求 (f(n)),即到达第 (n) 级台阶的所有走法。

通过这些步骤,你就能把原本复杂的问题拆解成小问题,逐步递推解决。

在这里插入图片描述


总结

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

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

相关文章

mysql表和表中记录的操作·2

表中字段的操作表中记录的操作SQL约束 1.表中字段的操作 字段/列column 知识点 在表中添加一列:alter table 表名 add 字段名 字段类型; 在表中删除一列:alter table 表名 drop 字段名; 在表中修改字段名和字段类型:alter table 表名…

IO零拷贝技术

01背景介绍 相信不少的网友,在很多的博客文章里面,已经见到过零拷贝这个词,会不禁的发出一些疑问,什么是零拷贝? 从字面上我们很容易理解出,零拷贝包含两个意思: 拷贝:就是指数据从…

Lesson1 - 操作系统概述与硬件视角

文章目录 什么是操作系统操作系统的形成 从程序看OS提出问题:从hello world文件开始目前编译器帮我们解决了诸多问题gcc的编译过程 CPU的运作CPU对任务的切换 什么是操作系统 操作系统 Operating System 是一组控制和管理计算机 硬件 和 软件 资源合理地对各类作业…

深入理解NumPy库:常用函数详解与数组操作指南

在数据科学和数值计算领域,NumPy无疑是一个强大的工具,它为Python提供了高效的多维数 组处理能力。无论是进行数据分析、构建机器学习模型,还是进行复杂的科学计算,NumPy都是 不可或缺的核心库之一。 numpy.array 是 NumPy 库中…

Python 从入门到实战34(实例2:绘制蟒蛇)

我们的目标是:通过这一套资料学习下来,通过熟练掌握python基础,然后结合经典实例、实践相结合,使我们完全掌握python,并做到独立完成项目开发的能力。 上篇文章我们讨论了数据库MySQL操作的相关知识。今天学习一个使用…

C语言指针plus版练习

上期我们讲了进阶的指针,本期内容我们来强化一下上期学的内容 一、字符串左旋 实现一个函数,可以左旋字符串中的k个字符。 1.1 分析题目 假设字符串为abcde,左旋一个以后就变成bcdea,就是把第一个字符移到一个新的变量里面&#…

5G NR BWP 简介

文章目录 BWP介绍BWP 分类BWP相关总结 BWP介绍 5G NR 系统带宽比4G LTE 大了很多,4G LTE 最大支持带宽为20MHz, 而5G NR 的FR1 最大支持带宽为100MH在, FR2 最大支持带宽为 400MH在。带宽越大,意味了终端功耗越多。为了减少终端的…

哪款百元头戴式耳机性价比高?四款大火爆全网的机型盘点推荐!

在繁忙的生活节奏中,寻找一片属于自己的宁静空间,成为了许多人的内心渴望。头戴式降噪耳机,正是那把打开音乐世界的钥匙。它不仅能够隔绝外界的喧嚣,还能将您带入一个纯净无瑕的音乐世界。无论是沉浸在古典乐的悠扬旋律中&#xf…

数据服务-存储服务(NFS)

1.概述 存储: 用于存放用户上传的内容(数据),一般应用在网站集群中 如果不使用存储,用户上传的数据就直接存放在网站服务器上了,用户下次访问就可能找不到 如果使用存储,用户上传的内容存放在存储上面,用户访问就会访问存储. 位置: 网站后排. 2. 存储分类 分类说明硬件存储硬件…

【高等数学学习记录】函数的极限

一、知识点 (一)知识结构 #mermaid-svg-Dz0Ns0FflWSBWY50 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-Dz0Ns0FflWSBWY50 .error-icon{fill:#552222;}#mermaid-svg-Dz0Ns0FflWSBWY50 .erro…

KiCad 综合笔记

开窗 选中顶层或者底层 Mask 层,然后进行覆铜: 四层板 KiCad Tutorial - How to make a 4 layer PCB https://bbs.elecfans.com/jishu_2365544_1_1.html 虽然在“电路板设置”中,可以选择铜层的类型,但如果选择了“电源层”,除了用于告诉“Free router”布线器在自动布…

vue3+vite@4+ts+elementplus创建项目详解

1、第一步创建项目cnpm init vite4 2、设置vue3.2局域网可访问配置: 找到项目路径下的package.json目录下找到script对象下面添加一下代码: "serve": "vite --host 0.0.0.0" 启动项目命令不在是dev而是:cnpm run serve 3…

Linux中的进程信号

目录 进程信号 kill/raise/abort 硬件异常产生信号 由软件条件产生信号 信号在内核中的表示示意图 pending: block: 信号集操作函数 sigprocmask 进程信号 信号量和信号不同 信号量的本质是计数器,计数器可以被多进程同时看到。可以对资源进行预定。 所有进…

OpenJudge | 置换选择排序

总时间限制: 1000ms 内存限制: 65536kB 描述 给定初始整数顺串,以及大小固定并且初始元素已知的二叉最小堆(为完全二叉树或类似完全二叉树,且父元素键值总小于等于任何一个子结点的键值),要求利用堆实现置换选择排序&a…

程序员如何在 AI 时代保持核心竞争力

前言 随着 AIGC 大语言模型的不断涌现,AI 辅助编程工具的普及正在深刻改变程序员的工作方式。在这一趋势下,程序员面临着新的挑战与机遇,需要思考如何应对以保持并提升自身的核心竞争力。 目录 一、AI 对编程工作的影响 (一&…

一、走进新语言

走进新语言 介绍环境配置JDK配置Kotlin配置 开发工具代码基本结构程序注释 介绍 Kotlin是一种现代但已经成熟的编程语言,旨在让开发人员更快乐。它简洁、安全、可与Java和其他语言互操作,并提供了许多在多个平台之间重用代码的方法。它由JetBrains公司于…

2.JUC

掌握 Java 并发编程,熟悉线程池、并发容器以及锁的机制,如 sychronized、ReentrantLock、AQS等。 2.0 并发基础 线程等待唤醒机制LockSupport (3种) 方式一:使用Object中的wait()方法让线程等待,使用Object中的notify()方法唤醒…

数据结构 ——— 单链表oj题:链表分割(带哨兵位单向不循环链表实现)

目录 题目要求 手搓简易单链表 代码实现 题目要求 现有一链表的头指针 ListNode* head ,给一定值 x ,编写一段代码将所有小于 x 的节点排在其余节点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头节点 举例说明&a…

【包教包会】2D图片实现3D透视效果(支持3.x、支持原生、可合批)

将去年写的SpriteFlipper从2.x升级到3.x。 如果需要2.x版本或需要了解算法思路,请移步:https://blog.csdn.net/weixin_42714632/article/details/136745051 优化功能:可同时绕X轴和Y轴旋转,两者效果会叠加。 完美适配Web、原生…

typescript使用webpack打包编译问题

解决方案:在webpack.config.js中的mdule.exports中设置mode。 再次运行npm run start即可。