【算法统治世界】动态规划 个人笔记总结

 🎉🎉欢迎光临🎉🎉

🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀

🌟特别推荐给大家我的最新专栏《数据结构与算法:初学者入门指南》📘📘

希望能和大家一起学习!共同进步!

这是苏泽的个人主页可以看到我其他的内容哦👇👇

努力的苏泽icon-default.png?t=N7T8http://suzee.blog.csdn.net

这段时间刷了几十道dp感觉人都要刷傻了 光刷题不行 还是要思考和总结 这篇纯当个人笔记

目录

动态规划的本质

动态规划其实都能归结为有限状态自动机和有向无环图

动态规划如何破局?

使用的条件

如何做?

设计状态

确定状态转移方程

确定初始状态

动态规划的几大类 +例题讲解

1. 背包问题(Knapsack Problem)

例题:0-1背包问题

2. 最长公共子序列(Longest Common Subsequence, LCS)问题

例题:最长公共子序列

3. 最大子序列和问题(Maximum Subarray Problem)

例题:最大子序列和

4. 硬币找零问题(Coin Change Problem)

例题:硬币找零

5. 矩阵链乘法问题(Matrix Chain Multiplication Problem)

例题:矩阵链乘法

坑点

容易忽略“动态”

错在把一开始的那个a[1]就当做了接龙子序列的最长序列             但实则并不一定  或者说  错在没有理解“最少”的含义


动态规划的本质

动态规划其实都能归结为有限状态自动机和有向无环图

动态规划可以被视为一种有限状态自动机,其中每个状态代表了问题的一个子集,状态之间的转移代表了子问题之间的关联。在有向无环图(Directed Acyclic Graph,简称DAG)中,每个节点代表一个状态,而边则代表了状态之间的转移关系。通过这种方式,动态规划将问题转化为在一个DAG上寻找最优路径的问题。

动态规划如何破局?

动态规划的关键在于如何设计状态和状态转移方程,以及如何确定初始状态。以下是动态规划的一般步骤:

使用的条件

在应用动态规划之前,我们需要确保问题满足以下条件:

  1. 最优化原理:问题能够在其子问题的基础上构造出最优解。
  2. 重叠子问题:问题可以被分解为相互重叠的子问题,且子问题的解可以被重复使用。
  3. 有限状态数:状态的数量是有限的,且满足状态数*状态转移数<10^6的条件,以保证算法的可行性。

如何做?

设计状态

设计状态是动态规划中最为关键的一步。状态应该能够唯一地表示问题的某个阶段,同时包含所有必要的信息以决定下一步的行动。状态的设计需要根据具体问题的特点来进行,常见的状态表示方法包括:

  • 位置:在序列问题中,可以用位置来表示状态。
  • 剩余元素:在涉及选择的问题中,可以用剩余可选元素的数量来表示状态。
  • 部分结果:在需要构造结果的问题中,可以用已经得到的部分结果来表示状态。

确定状态转移方程

状态转移方程描述了状态之间的转移关系,它定义了如何从一个或多个状态得到新的状态。状态转移方程的设计需要满足最优化原理,确保能够从子问题的最优解得到原问题的最优解。 常见的状态转移方程类型包括:

  • 相加或相乘:当问题涉及到数值的累加或累乘时。
  • 选择:当问题需要在多个选项中选择一个最优的选项时。
  • 条件转移:当状态转移依赖于某些条件或属性时。

确定初始状态

初始状态是动态规划的起点,它通常代表了问题规模最小的情况下的状态。确定初始状态需要根据问题的具体背景和定义来进行。

动态规划的几大类 +例题讲解

1. 背包问题(Knapsack Problem)

背包问题是一种典型的组合优化问题,通常描述为有一个可以装载重量为W的背包和一组物品,每个物品有自己的重量和价值,目标是选择物品的组合,使得背包中物品的总重量不超过W,且总价值最大。

例题:0-1背包问题

描述:给定n个物品,每个物品有自己的重量w[i]和价值v[i],以及一个最大承重W的背包。求解如何选择物品放入背包,使得背包中物品的总价值最大。

解题思路:定义dp[i][j]为前i个物品中,能够装入容量为j的背包的最大价值。状态转移方程为:

 

dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i])

其中,dp[i-1][j]表示不选择第i个物品,而dp[i-1][j-w[i]] + v[i]表示选择第i个物品。

2. 最长公共子序列(Longest Common Subsequence, LCS)问题

LCS问题是一种经典的字符串匹配问题,通常描述为有两个字符串,求解这两个字符串的最长公共子序列的长度。

例题:最长公共子序列

描述:给定两个字符串s1s2,求解它们的最长公共子序列。

解题思路:定义dp[i][j]s1的前i个字符和s2的前j个字符的最长公共子序列的长度。状态转移方程为:

 

if s1[i-1] == s2[j-1] dp[i][j] = dp[i-1][j-1] + 1 else dp[i][j] = max(dp[i-1][j], dp[i][j-1])

其中,相等的情况表示找到了一个公共字符,不相等的情况则取两个方向的最大值。

3. 最大子序列和问题(Maximum Subarray Problem)

最大子序列和问题是一种数组优化问题,通常描述为给定一个整数数组,找到一个连续子数组,使得其和最大。

例题:最大子序列和

描述:给定一个整数数组nums,返回其中最大子序列的和。

解题思路:定义tempSum为当前子数组的和,maxSum为当前找到的最大子序列和。遍历数组,对于每个元素,更新tempSummaxSum

 

if tempSum < 0 tempSum = nums[i] else tempSum += nums[i] if tempSum > maxSum maxSum = tempSum

这种方法的时间复杂度为O(n)。

4. 硬币找零问题(Coin Change Problem)

硬币找零问题是一种货币找零问题,通常描述为给定不同面额的硬币和一个总金额,求解凑成总金额所需的最少硬币个数。

例题:硬币找零

描述:给定不同面额的硬币coins和一个总金额amount,返回凑成总金额所需的最少硬币个数。

解题思路:定义dp[i]为组合成金额i所需的最少硬币个数。状态转移方程为:

 

dp[i] = min(dp[i], dp[i-c] + 1),对于所有c属于coins

其中,dp[i-c] + 1表示使用面额为c的硬币凑成金额i。

5. 矩阵链乘法问题(Matrix Chain Multiplication Problem)

矩阵链乘法问题是一种动态规划在矩阵乘法中的应用问题,通常描述为给定一系列矩阵,求解将它们乘在一起的最小计算成本。

例题:矩阵链乘法

描述:给定一系列矩阵的维度p[1...n],其中p[i]表示第i个矩阵的行数和列数,求解按照哪种顺序乘这些矩阵,使得计算成本最小。

解题思路:定义dp[i][j]为计算矩阵链p[i...j]的最小成本。状态转移方程为:

 

dp[i][j] = min{dp[k][j] + dp[i][k-1] + p[i]*p[k]*p[j]》,对于所有i ≤ k < j

其中,dp[k][j]dp[i][k-1]表示分别计算矩阵链p[i...k]p[k+1...j]的成本,而p[i]*p[k]*p[j]是这两个链相乘时的计算成本。

坑点

容易忽略“动态”

把一个线性的状态作为“固定点” 一直延展 

就像这道 接龙数列:P9242 [蓝桥杯 2023 省 B] 接龙数列 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

我一开始的错误

public class MyWrong {public static void main(String[] args) {Scanner in=new Scanner(System.in);int N=in.nextInt();long[] a=new long[N+1];long length =0;for (int i = 1; i <=N ; i++) {a[i]=in.nextInt();length++;}long ans=0;int now=getHead(a[1]);for (int i = 1; i <=N ; i++) {//错在把一开始的那个a[1]就当做了接龙子序列的最长序列// 但实则并不一定  或者说  错在没有理解“最少”的含义if (now==getHead(a[i])){ans++;now=(int)a[i]%10;}}System.out.println(length-ans);}static public int getHead(long l){while (l>=10){l/=10;}return (int)l;}
}

错在把一开始的那个a[1]就当做了接龙子序列的最长序列
             但实则并不一定  或者说  错在没有理解“最少”的含义

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

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

相关文章

分布式主键ID生成策略

业务系统对分布式ID的要求 唯一性&#xff1a;在分布式系统中&#xff0c;每个节点都需要生成唯一的标识符来确保数据的唯一性。传统的单点生成ID方式无法满足分布式环境下的需求&#xff0c;而分布式ID能够在整个系统中保证每个节点生成的ID都是唯一的。 顺序性&#xff1a;某…

CSS设置网页颜色

目录 前言&#xff1a; 1.颜色名字&#xff1a; 2.十六进制码&#xff1a; 3.RGB&#xff1a; 4.RGBA&#xff1a; 5.HSL&#xff1a; 1.hue&#xff1a; 2.saturation&#xff1a; 3.lightness&#xff1a; 6.HSLA&#xff1a; 前言&#xff1a; 我们在电脑显示器&…

Linux 多线程

目录 初识线程 线程的概念 Linux下的线程 线程优缺点 线程控制 线程创建 线程终止 线程等待 线程分离 线程取消 其它 线程互斥 互斥的概念 互斥锁的使用 锁的本质 线程同步 线程同步的概念 条件变量的概念 条件变量的使用 信号量 信号量的概念 信号量接口…

007 CSS的继承和层叠 元素特性

文章目录 CSS属性的继承CSS属性的层叠选择器的权重 HTML元素的类型编写HTML注意事项元素隐藏方法CSS属性-overflowCSS样式不生效可能原因 CSS属性的继承 如果一个属性具备继承性&#xff0c;那么在该元素上设置后&#xff0c;它的后代元素都可以继承这个属性 如果后代元素自己…

如何将平板或手机作为电脑的外接显示器?

先上官网链接&#xff1a;ExtensoDesk 家里有一台华为平板&#xff0c;自从买回来以后除了看视频外&#xff0c;基本没什么作用&#xff0c;于是想着将其作为我电脑的第二个屏幕&#xff0c;提高我学习办公的效率&#xff0c;废物再次利用。最近了解到华为和小米生态有多屏协同…

android11 SystemUI入門之KeyguardPatternView解析

view层级树为&#xff1a; 被包含在 keyguard_host_view.xml中 。 <?xml version"1.0" encoding"utf-8"?> <!-- This is the host view that generally contains two sub views: the widget viewand the security view. --> <com.andro…

关于Emulator和Simulator的探讨

由于写论文需要&#xff0c;仔细的学习和比对一下Emulator和Simulator的概念。原来“Emulator专门指硬件模拟&#xff0c;Simulator专门指软件模拟”的观点是不正确的&#xff0c;于是查看了很多文章的解释。同时也提醒自己&#xff0c;做科研一定要认真细致&#xff0c;无论看…

CLR学习

视频链接&#xff1a;《CLR十分钟》系列之CLR运行模型_哔哩哔哩_bilibili 什么是 CLR 公共语言运行时&#xff08;Common Language Runtime CLR&#xff09; 是一个可有多种编程语言使用的 运行时&#xff0c;CLR 的核心功能&#xff08;比如 内存管理&#xff0c;程序集加载…

Node.JS多线程PromisePool之promise-pool库实现

什么是Promise Pool Map-like, concurrent promise processing for Node.js. Promise-Pool是一个用于管理并发请求的JavaScript库&#xff0c;它可以限制同时进行的请求数量&#xff0c;以避免过多的请求导致服务器压力过大。使用Promise-Pool可以方便地实现对多个异步操作的并…

HarmonyOS 开发-使用SideBarContainer侧边栏淡入淡出动效实现案例

介绍 在2in1或平板上&#xff0c;群聊侧边栏是一种较为常用的功能&#xff0c;虽然HarmonyOS已经具备了基本的动效&#xff0c;但是部分情况下开发者可能有定制侧边栏动效的需求&#xff0c;本例主要介绍了如何基于显式动画实现侧边栏的淡入淡出动效。 效果图预览 使用说明&a…

C#中值类型与引用类型的存储

目录 值对象与引用对象的存储 引用对象的成员存储 值对象与引用对象的存储 数据项的类型定义了存储数据需要的内存大小及组成该类型的数据成员。类型还决定了对象在内存中的存储位置——栈或堆。 C#中类型分为两种&#xff1a;值类型和引用类型&#xff0c;这两种类型的对象…

天机学堂踩坑笔记

相关资源链接&#xff1a; Md笔记&#xff1a;蓝奏云地址 在线笔记&#xff1a;飞书笔记地址 相关视频教程及配套课件&#xff1a; 链接&#xff1a;百度云地址 提取码&#xff1a;hmz1 1. Day01 初识项目 1.1 OpenEuler 22.03LTS yum换源失败 适用于OpenEuler版本为22.03LT…

1.Hexo安装和环境搭建引导

Hexo是一个依赖于一个名为nodejs的程序 因此安装它的方式在Mac和Windows上实际上是一样的 为了在电脑上安装Hexo 需要做两件事 nodejs&#xff0c;基本上是hexo依赖运行的JavaScript框架 Node.js — Run JavaScript Everywheregit&#xff0c;是一个程序&#xff0c;用来管理电…

BurpSuite保姆级教程

Burp Suite下载,破解,代理web,代理模拟器 (一)为Burp Sutie下载运行执行脚本环境(Java) 1.Java官网下载地址&#xff1a;https://www.oracle.com/java/technologies/ 下载Java SE 17.0.8(LTS) 备注&#xff1a;1.2023版Burp Suite 完美的运行脚本的环境是Java17 2.Java8不支持…

数据仓库实践

什么是数据仓库&#xff1f; 数据仓库是一个用于存储大量数据并支持数据分析与报告的系统。它通常用于集成来自不同来源的数据&#xff0c;提供一个统一的视图&#xff0c;以便进行更深入的分析和决策。 数据仓库的主要优势&#xff1f; 决策支持&#xff1a;为企业决策提供可靠…

2024年,AIGC如何渗透我的生活?

本篇博文列举本人最常用的 6 款app中 AIGC 发挥的功能及作用。 Cursor 作为一名科研工作者&#xff0c;平时最常用的软件就是代码编写工具。Cursor内置的Chat功能&#xff0c;可以辅助完成代码编辑&#xff0c;随时随地实现ChatGPT私有化。 Grammarly 可用于Word和Overleaf等…

vue快速入门(三)差值表达式

注释很详细&#xff0c;直接上代码 上一篇 新增内容 插值表达式基本用法插值表达式常用公式 源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-wid…

Jmeter针对多种响应断言的判断

有时候response返回的结果并非一种&#xff0c;有多种&#xff0c;需要对这几种进行判断的时候需要使用Bean Shell。 &#xff08;1&#xff09;首先获取响应数据 String response prev.getResponseDataAsString(); ResponseCode 响应状态码 responseHeaders 响应头信息 res…

c++的学习之路:17、stack、queue与priority_queue

摘要 本文主要是介绍一下stack、queue、priority_queue的使用以及模拟实现&#xff0c;文章末附上代码以及思维导图。 目录 摘要 一、stack的介绍和使用 1、stack的介绍 2、stack的使用 3、stack的模拟实现 二、queue的介绍和使用 1、queue的介绍 2、queue的使用 3、…

每日一题:矩阵置零

给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]]使用两个标记变量。 class Sol…