数据结构-动态规划策略

  • 动态规划

    • 1.理解动态规划思想

      • 基本概念
        • 重叠子问题:原问题可以分解为若干个子问题,且这些子问题之间存在重复部分。也就是说,为了解决一个子问题,我们需要多次求解相同的子子问题。例如,在计算斐波那契数列时,计算第n项需要知道第n-1项和第n-2项,而计算第n-1项又需要知道第n-2项和第n-3项,如此反复,子问题被反复计算。
        • 最优子结构:原问题的最优解可以通过其子问题的最优解构造出来。这意味着,要找到整个问题的最优解,必须先确定子问题的最优解。例如,在求解最短路径问题时,从起点到终点的最短路径必然包含从起点到某个中间节点的最短路径。
      • 核心思想
        • 主要用于解决具有重叠子问题和最优子结构性质的问题。动态规划的核心思想是将原问题分解为相互重叠的子问题,并通过自底向上或自顶向下的方式逐步求解子问题,存储并利用已计算过的子问题结果(称为“状态”或“阶段”),避免重复计算,从而高效地求得原问题的最优解。
    • 2.算法实现过程(状态与状态转移方程)

      • 状态的定义:明确问题中的状态变量及其取值范围。状态通常代表了问题在某一阶段或某一时刻的具体情况。
      • 状态转移方程:建立状态之间的递推关系,即如何从一个或多个较小规模的子问题状态计算出当前状态的值。这是动态规划的核心步骤,它确保了问题的求解能够以自底向上或自顶向下的方式进行。
      • 边界条件:确定递归过程的终止条件或初始状态值。这通常是问题规模最小或没有子问题时的状态值。例如,在斐波那契数列中,边界条件为 F(0) = 0 和 F(1) = 1。
    • 3.动态规划实现方式

      • 记忆化搜索(自顶向下)
        1. 编写递归函数,遵循“先调用后计算”的原则,同时在函数内部添加缓存(如哈希表或数组),存储已计算过的子问题结果。
        2. 在每次递归调用时,首先检查缓存中是否存在对应子问题的解,若存在则直接返回;若不存在,则计算该子问题的解并将其存入缓存,再返回结果。
      • 迭代法(自底向上)
        • 使用循环结构遍历状态空间,按照问题规模从小到大的顺序,依次计算所有子问题的解。
        • 根据状态转移方程,利用已计算好的较小规模子问题的解来更新当前状态的值。
        • 将每个子问题的解保存在一个表格(如二维数组)中,便于后续访问。
    • 4.动态规划的适用条件

      • 最优子结构
        • 问题的最优解包含其子问题的最优解。换句话说,要找到原问题的最优解,必须先确定其子问题的最优解。这意味着,问题的最优解可以通过组合子问题的最优解来构建,而无需考虑非最优的子问题解。
      • 重叠子问题
        • 在解决问题的过程中,相同的子问题会被多次遇到和求解。如果不采取措施避免重复计算,这种重复会导致不必要的计算开销,降低算法效率。
        • 动态规划通过保存已经计算过的子问题结果,避免了对同一子问题的重复求解,从而提高了效率。例如,在计算斐波那契数列时,计算第n项需要知道第n-1项和第n-2项,而计算第n-1项又需要知道第n-2项和第n-3项,如果没有缓存先前的结果,就会出现大量的重复计算。
      • 无后效性
        • 当前状态的决策只依赖于当前状态本身及之前的状态,而不依赖于未来状态或之后的决策。也就是说,一旦确定了一个状态的值,未来的决策不会影响这个状态值的变化。
        • 无后效性保证了状态转移过程的确定性,使得我们可以放心地根据当前状态计算下一个状态,而不需要担心未来决策会反过来影响当前状态的计算。
    • 5.动态规划的时间复杂度分析

      • 状态空间大小
        • 状态数(n):问题中可能存在的不同状态的数量。这通常由状态变量的取值范围决定。例如,在经典的0/1背包问题中,状态变量可能包括物品编号和背包剩余容量,状态数随物品数量和背包容量的不同而变化。
        • 状态维度(d):问题中的状态变量个数。单变量问题通常对应一维状态空间,多变量问题则对应多维状态空间。状态维度会影响状态转移所需的计算次数。
      • 状态转移次数
        • 状态转移方程:分析状态转移方程以确定计算一个状态值所需的状态转移次数。这通常涉及到对状态空间中相邻状态(或相关状态)的访问次数。
        • 循环结构:如果使用迭代法(自底向上)实现,可以通过分析循环结构来确定状态转移次数。例如,双层循环通常对应状态转移次数为 O(n^2),三层循环则可能对应 O(n^3)。
      • 状态转移复杂度
        • 单次转移操作:计算一个状态值所需的基本操作次数。
        • 总转移复杂度:将单次转移操作的复杂度乘以状态转移次数,得到总的转移复杂度
      • 边界条件处理
        • 初始化时间:处理边界条件所需的时间,通常为常数时间或与状态空间大小成线性关系。
        • 结果提取时间:从最终状态或状态表中提取最终答案所需的时间,同样通常为较低阶复杂度。
      • 总体时间复杂度
        • 动态规划算法的总体时间复杂度通常由上述各部分复杂度的最高阶项决定。
    • 6.典型动态规划问题

      • 最长上升子序列
        • 问题描述:给定一个整数序列,找到其中最长的严格递增子序列(子序列中的元素严格递增,且不一定是连续的)的长度。
        • 动态规划思想
          • 状态定义:设 dp[i] 表示以原序列中第 i 个元素结尾的最长上升子序列的长度。
          • 状态转移:对于每个位置 i,考虑其前面所有较小的元素(A[j],j < i),若存在 A[j] < A[i],则以 A[i] 结尾的最长上升子序列长度至少为 dp[j] + 1。取所有这样的 dp[j] + 1 中的最大值作为 dp[i] 的值。
          • 动态规划方程:dp[i] = max(dp[j] + 1),其中 j 满足 0 <= j < i 且 A[j] < A[i]。
      • 0-1背包问题
        • 问题描述:给定一组物品,每种物品有一个重量 w_i 和一个价值 v_i,以及一个背包的容量 W。要求在不超过背包容量的前提下,选择物品放入背包,使得背包中物品的总价值最大。
        • 动态规划思想
          • 状态定义:设 dp[i][w][i][w]表示考虑前 i 件物品,背包容量为 w 时可以获得的最大价值。
          • 状态转移:对于每个物品 i 和背包容量 w,有两种选择:① 不放入物品 i,此时背包价值为 dp[i-1][w];② 放入物品 i,若 w >= w_i,则背包价值为 dp[i-1][w-w_i] + v_i。取两者中价值较大者作为 dp[i][w] 的值。
          • 动态规划方程:dp[i][w] = max(dp[i-1][w], dp[i-1][w-w_i] + v_i),其中 w >= w_i;否则 dp[i][w] = dp[i-1][w]。
      • 最长公共子序列
        • 问题描述:给定两个字符串 str1 和 str2,找到它们的最长公共子序列(子序列中的字符按原顺序排列,且不一定连续)的长度
        • 动态规划思想
          • 状态定义:设 dp[i][j] 表示字符串 str1 前 i 个字符和字符串 str2 前 j 个字符的最长公共子序列的长度。
          • 状态转移:对于每对字符位置 (i, j),若 str1[i-1] == str2[j-1],说明当前i,j字符相同可以加入公共子序列,长度增加1,即 dp[i][j] = dp[i-1][j-1] + 1;否则,选择在 str1 或 str2 中保留更长的子序列,即 dp[i][j] = max(dp[i-1][j], dp[i][j-1])。
          • 动态规划方程:若 str1[i-1] == str2[j-1]),dp[i][j] = dp[i-1][j-1] + 1,否则 dp[i][j] = max(dp[i-\1][j], dp[i][j-1])。
      • 最大子数组之和
        • 问题描述:给定一个整数数组,找到其中具有最大和的连续子数组。
        • 动态规划思想
          • 状态定义:设 dp[i] 表示以原数组中第 i 个元素结尾的连续子数组的最大和。
          • 状态转移:对于每个位置 i,计算以 A[i] 结尾的子数组和,有两种情况:① 包含前一个元素 A[i-1],则子数组和为 dp[i-1] + A[i];② 只包含当前元素 A[i],子数组和为 A[i]。取两者中和较大的作为 dp[i] 的值。
          • 动态规划方程:dp[i] = max(dp[i-1] + A[i], A[i]).其中 i > 0;dp[0] = A[0](初始化)。

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

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

相关文章

java实现chatGPT SDK

搭建一个 ChatGPT-SDK 组件工程&#xff0c;专门用于封装对 OpenAI 接口的使用。由于 OpenAI 接口本身较多&#xff0c;并有各类配置的设置&#xff0c;所以开发一个共用的 SDK 组件&#xff0c;更合适我们在各类工程中扩展使用 整个流程为&#xff1a;以会话模型为出口&#x…

C++笔试强训day3

目录 1.简写单词 2.dd爱框框 3.除2&#xff01; 1.简写单词 链接 我的思路超级简单&#xff0c;就是将输入的每个string存入vector&#xff0c;然后遍历每个string的第一个元素&#xff0c;如果为小写字母&#xff0c;就-32存入&#xff0c;若为大写&#xff0c;则直接存入。…

Docker in Docker的原理与实战

Docker in Docker&#xff08;简称DinD&#xff09;是一种在Docker容器内部运行另一个Docker实例的技术。这种技术允许用户在一个隔离的Docker容器中创建、管理和运行其他Docker容器&#xff0c;从而提供了更灵活和可控的部署选项。以下是DinD的主要特点&#xff1a; 隔离性&am…

react 封装请求axios,直接调用即可

概要 我们在开发项目的时候&#xff0c;常常会遇到接口请求的问题的&#xff0c;若我们不进行接口的统一管理&#xff0c;代码开发不仅多而且很麻烦容易出错&#xff0c;也不利于项目的维护。下面我们一下学习下react项目中将如何封装请求&#xff0c;也从另一个方面中少写一些…

Maven实战—搭建微服务 Maven 工程架构

需求案例&#xff1a;搭建一个电商平台项目&#xff0c;该平台包括用户服务、订单服务、通用工具模块等。 项目架构&#xff1a; 用户服务&#xff1a;负责处理用户相关的逻辑&#xff0c;例如用户信息的管理、用户注册、登录等。订单服务&#xff1a;负责处理订单相关的逻辑…

mac 使用nvm配置nodejs

您可以按照以下步骤在Mac上安装指定版本的Node.js&#xff1a; 首先&#xff0c;请确保您已经安装了Homebrew。如果没有&#xff0c;请在终端中运行以下命令来安装Homebrew&#xff1a; /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install…

Swift网络编程

Swift网络编程涉及到一些重要的方面&#xff0c;包括URLSession的使用、数据解析&#xff08;JSON/XML&#xff09;以及网络请求的封装与管理。下面将详细介绍这三个方面的内容。 1.URLSession的使用: URLSession是Swift中用于网络请求的核心类。它提供了一系列方法来创建和管…

使用示例解释.NET中的Mocking是什么?

让我们踏上探索.NET软件开发中Mocking概念的旅程&#xff0c;让我们深入了解Mocking是多么简单易懂、易于访问。请与我一起穿越这个主题&#xff0c;我将涵盖以下内容&#xff1a; 理解Mocking&#xff1a;为何它对于构建强大的测试策略至关重要。探索一些最常见的Mocking库&a…

Ansible组件说明

1.Ansible Inventory 工作当中有不同的业务主机&#xff0c;我们需要在把这些机器信息存放在inventory里面&#xff0c;ansible默认的inventory的文件是/etc/ansible/hosts&#xff0c;也可以通过ANSIBLE_HOSTS环境变量来指定或者运行ansible和ansible-playbook的时候用-i参数临…

Spring Boot 学习(6)——组件注册

也是学得头晕眼花&#xff0c;终于知道学有多么难了&#xff0c;更知道教有多么难了…… 各位大神们出的教程终归和正规出版社还是差距的&#xff0c;我觉得是没有“审定”&#xff0c;这对于大多数做教程的人来说这应该通病&#xff1a;自己做&#xff08;讲&#xff09;的东西…

视频教程下载:用ChatGPT玩转海外抖音TikTok

CHATGPT for TikTok是一门前沿课程&#xff0c;旨在帮助您充分发挥TikTok广告活动的全部潜力。随着数字营销的爆炸性增长&#xff0c;企业需要使用先进的工具来保持竞争优势。在这门课程中&#xff0c;您将学习如何利用CHATGPT——一种先进的人工智能工具——来创建与目标受众产…

有没有手机上使用的库存软件

库存软件是一种仓库的信息管理系统&#xff0c;它主要针对出库与入库这些数据进行管理&#xff0c;传统的库存管理都是在电脑上安装一个专门的数据库管理系统进行管理&#xff0c;这也是一种比较成熟的管理方式&#xff0c;那么有没有手机上使用的库存软件。 手机上使用的库存软…

k8s配置configmap指定到容器的指定文件

我们需要将名称为walletkey.properties的文件做成configmap&#xff0c;然后将walletkey.properties文件单独挂载出来到/data/walletkey.properties&#xff0c;且不能覆盖/data目录&#xff0c;具体如下 1、创建configmap configmap文件内容 其中walletkey.properties: >-引…

python语言零基础入门——注释、print()函数、input()函数

目录 一、注释 1.块注释 2.行内注释 3.多行注释 二、打印变量 1.print()函数&#xff1a;输出/打印指定内容 2.input()函数&#xff1a;输入指定内容 三、编程题&#xff1a;个人名片 一、注释 1.块注释 以#开始&#xff0c;直到本行结束都是注释为了保证代码的可读性…

科技的崛起:国内机器视觉蓬勃发展

文 | BFT机器人 在工业4.0的浪潮下&#xff0c;随着科技的蓬勃发展&#xff0c;机器视觉逐渐走入大众视野&#xff0c;机器视觉产品的普及范围也越来越广。 大家知道机器视觉的由来吗&#xff1f; 机器视觉的由来可以追溯到20世纪70年代&#xff0c;美国麻省理工学院&#xff…

STM32、ESP8266与MQTT连接阿里云物联网的串口通信异常解析

STM32、ESP8266与MQTT协议连接阿里云物联网平台时常见的串口通信异常介绍 在构建物联网应用时&#xff0c;STM32、ESP8266与MQTT协议的结合是实现设备与网络间稳定通信的关键。然而&#xff0c;在连接阿里云物联网平台的过程中&#xff0c;串口通信异常成为了一个常见的挑战。…

Docker常见命令学习

Docker 是一个开源的应用容器引擎&#xff0c;它允许开发者打包他们的应用以及应用的依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何支持 Docker 的系统上。以下是一些常用的 Docker 命令&#xff1a; docker run: 运行一个容器。例如&#xff0c;docker run -…

机器学习鸢尾花各种模型准确率对比

流程 获取数据集导入需要的包读取数据划分训练集和测试集调用各种模型比较准确率 获取数据集 链接&#xff1a;https://pan.baidu.com/s/1RzZyXsaiJB3e611itF466Q?pwdj484 提取码&#xff1a;j484 --来自百度网盘超级会员V1的分享导入需要的包 import pandas as pd impo…

Linux学习(嵌入式硬件知识)

EMMC eMMC&#xff08;嵌入式多媒体卡&#xff09;是一种内置型快闪存储解决方案&#xff0c;常见于嵌入式系统、移动设备和一些消费类电子产品中。它的设计集成了快闪存储器和控制器&#xff0c;并通过MMC&#xff08;多媒体卡&#xff09;接口连接到主处理器或主板上。这些是…

回归决策树的构建

回归决策树是一种决策树模型&#xff0c;顾名思义&#xff0c;它用于解决回归问题&#xff0c;即预测连续数值型的输出变量。它基于树状结构&#xff0c;通过一系列内部节点、分支和叶节点来建立数据特征与输出值之间的非线性关系。在构建回归决策树的过程中&#xff0c;数据集…