蓝桥杯备考随手记: 动态规划

1. 动态规划(Dynamic Programming,简称DP)是一种解决多阶段最优化问题的方法,它将问题分解成多个子问题,通过逐个求解子问题来求解原问题。

在动态规划中,每个子问题只需要求解一次,并将其结果保存起来,以便于下次需要时直接使用,避免重复计算。这种将问题分解成多个子问题并保存子问题的求解结果的方法,可以有效地提高求解问题的效率。

2. 动态规划通常包含以下几个步骤:

  1. 定义状态:根据问题的特点,定义状态表示问题的子问题的解。状态可以是一个或多个变量的组合,用来表示问题的不同特征或属性。状态可以是一个维度或多个维度的数组或矩阵。

  2. 划分阶段:将问题划分成多个阶段,每个阶段对应一个子问题。每个阶段的求解都依赖于上一个阶段的求解结果。

  3. 确定状态转移方程:根据子问题之间的关系,确定状态转移方程,即子问题的解与其他子问题的解之间的关系。状态转移方程描述了问题的递推关系,通常可以通过递归或迭代的方式求解。

  4. 确定初始状态:确定最小子问题的解,作为初始状态。初始状态是问题求解的起点,它是问题规模最小的情况下的解。

  5. 自底向上求解:根据状态转移方程,从最小子问题的解开始逐步求解更大规模的子问题的解。可以使用迭代的方式,从初始状态开始依次求解每个阶段的子问题,直到求解出原问题的最优解。

  6. 求解原问题:根据最大规模的子问题的解,求解原问题。最大规模的子问题的解即为原问题的最优解。

动态规划通常适用于具有最优子结构和重叠子问题性质的问题。最优子结构性质意味着问题的最优解可以由子问题的最优解推导出来。重叠子问题性质意味着在计算问题的最优解时,需要多次计算相同的子问题。

下面是一个使用动态规划求解斐波那契数列的例子,使用Java代码示范:

public class FibonacciDP {public static int fibonacci(int n) {// 创建一个数组用来保存子问题的解int[] dp = new int[n+1];// 初始化初始状态dp[0] = 0;dp[1] = 1;// 自底向上求解每个阶段的子问题的解for (int i = 2; i <= n; i++) {// 使用状态转移方程求解当前阶段的子问题的解dp[i] = dp[i-1] + dp[i-2];}// 返回原问题的最优解return dp[n];}public static void main(String[] args) {int n = 10;int result = fibonacci(n);System.out.println("斐波那契数列第 " + n + " 项的值为:" + result);}
}

运行上述代码,将输出斐波那契数列第 10 项的值为:55。这个例子中,我们使用动态规划的思想,将斐波那契数列的问题划分成多个子问题,并使用一个数组 dp 来保存子问题的解。通过状态转移方程 dp[i] = dp[i-1] + dp[i-2],我们逐步求解每个阶段的子问题的解,最终得到了斐波那契数列的最优解。

3. 下面介绍几个最常用的动态规划问题:

  1. 最长递增子序列(Longest Increasing Subsequence, LIS): 在一个给定的序列中,找到一个最长的子序列,使得子序列中的元素按照从小到大的顺序排列,并且子序列的长度最大化。

    动态规划是一种解决问题的思想,它通常用于解决具有重叠子问题和最优子结构性质的问题。使用动态规划解决LIS问题的思路是,通过构建一个辅助数组dp,dp[i]表示以第i个元素结尾的最长递增子序列长度。

    以下是在Java中使用动态规划解决LIS问题的示例代码:

    public class LIS {public static int lengthOfLIS(int[] nums) {int[] dp = new int[nums.length]; // 创建一个dp数组,用于存储以每个元素为结尾的最长递增子序列的长度Arrays.fill(dp, 1); // 初始化dp数组为1,每个元素默认自己就是一个递增子序列int maxLen = 1; // 用于存储最长递增子序列的长度// 从索引 1 开始遍历数组for (int i = 1; i < nums.length; i++) {// 遍历索引 i 之前的所有元素for (int j = 0; j < i; j++) {// 如果当前元素 nums[i] 大于 nums[j],说明可以将 nums[i] 添加到以 nums[j] 结尾的递增子序列中if (nums[i] > nums[j]) {// 更新当前最长递增子序列的长度dp[i] = Math.max(dp[i], dp[j] + 1);}}// 更新最长递增子序列的长度maxLen = Math.max(maxLen, dp[i]);}return maxLen;}public static void main(String[] args) {int[] nums = {10, 9, 2, 5, 3, 7, 101, 18};int lisLength = lengthOfLIS(nums);System.out.println("最长递增子序列的长度: " + lisLength);}
    }
  2. 0-1背包问题(0-1 Knapsack Problem):假设有一个背包,它能够容纳一定的重量(W)和价值(V)。现在有一组物品,每个物品有不同的重量(w)和价值(v),我们需要选择一些物品放入背包中,使得放入的物品总重量不超过背包的重量限制,并且使得放入的物品总价值最大化。

    动态规划是解决0-1背包问题的常用方法。它的基本思想是利用一个二维数组(dp数组)来记录在不同的背包容量和物品个数下的最大总价值。数组的行表示不同的物品个数,列表示不同的背包容量。通过填充dp数组,我们可以逐步求解出最优解。

    以下是使用动态规划解决0-1背包问题的Java代码:

    public class KnapsackProblem {public static int knapsack(int[] weights, int[] values, int maxWeight) {// 创建一个二维数组来存储最大总价值int[][] dp = new int[weights.length + 1][maxWeight + 1];// 填充dp数组for (int i = 1; i <= weights.length; i++) {for (int j = 1; j <= maxWeight; j++) {// 如果当前物品的重量大于当前背包容量,则不能放入背包,总价值等于上一个物品的价值if (weights[i - 1] > j) {dp[i][j] = dp[i - 1][j];}// 如果当前物品的重量小于等于当前背包容量,则可以选择放入或不放入else {// 不放入当前物品,总价值等于上一个物品的价值int notPut = dp[i - 1][j];// 放入当前物品,总价值等于上一个物品的价值加上当前物品的价值int put = dp[i - 1][j - weights[i - 1]] + values[i - 1];// 取较大值作为当前背包容量下的最大总价值dp[i][j] = Math.max(notPut, put);}}}// 返回最大总价值return dp[weights.length][maxWeight];}public static void main(String[] args) {int[] weights = {2, 3, 4, 5};int[] values = {3, 4, 5, 6};int maxWeight = 8;int maxTotalValue = knapsack(weights, values, maxWeight);System.out.println("最大总价值为:" + maxTotalValue);}
    }
    
  3. 最长公共子序列(Longest Common Subsequence,LCS):给定两个或多个序列中最长的公共子序列。子序列是从给定序列中删除一些元素(可能为零),并保持相对顺序的序列。

    动态规划是解决LCS问题的常用方法。基本思想是:设有两个序列A和B,分别以A[i]和B[j]结尾的LCS长度为dp[i][j]。通过迭代计算dp[i][j],可以得到最长公共子序列的长度。

    在Java中,我们可以使用二维数组来存储dp的值。代码如下所示:

    public class LCS {public static int getLCSLength(String s1, String s2) {int m = s1.length();int n = s2.length();// 创建一个二维数组来存储dp的值int[][] dp = new int[m + 1][n + 1];// 初始化第一行和第一列为0,表示空序列for (int i = 0; i <= m; i++) {dp[i][0] = 0;}for (int j = 0; j <= n; j++) {dp[0][j] = 0;}// 根据状态转移方程计算dp的值for (int i = 1; i <= m; i++) {for (int j = 1; j <= n; j++) {if (s1.charAt(i - 1) == s2.charAt(j - 1)) {dp[i][j] = dp[i - 1][j - 1] + 1;} else {dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);}}}// 返回dp的最后一个元素,即最长公共子序列的长度return dp[m][n];}public static void main(String[] args) {String s1 = "ABCD";String s2 = "BCDE";int lcsLength = getLCSLength(s1, s2);System.out.println("最长公共子序列的长度为:" + lcsLength);}
    }
    

通过动态规划,可以将原问题划分成多个子问题,并通过保存子问题的解来避免重复计算,从而有效地求解问题。 

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

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

相关文章

LinkedHashMap部分底层源码解析

JDK版本为1.8.0_271&#xff0c;LinkedHashMap继承了HashMap&#xff0c;LinkedHashMap在HashMap的基础上维护了一个双向链表&#xff0c;实现了可以根据插入顺序/访问顺序&#xff08;accessOrderfalse/true&#xff09;访问Map集合。 关于HashMap的原理可以参考HashMap部分底…

RabbitMQ-死信队列常见用法

目录 一、什么是死信 二、什么是死信队列 ​编辑 三、第一种情景&#xff1a;消息被拒绝时 四、第二种场景&#xff1a;. 消费者发生异常&#xff0c;超过重试次数 。 其实spring框架调用的就是 basicNack 五、第三种场景&#xff1a; 消息的Expiration 过期时长或队列TTL…

详细介绍ContextMenuPolicy

ContextMenuPolicy 是 Qt 框架中 QWidget 类的一个枚举类型&#xff0c;它定义了如何响应和处理鼠标右键点击事件&#xff0c;即上下文菜单的策略。上下文菜单是一种临时出现的菜单&#xff0c;通常出现在用户执行特定操作&#xff08;如右键点击&#xff09;时&#xff0c;提供…

基于特征的多模态生物信号信息检索与自相似矩阵:专注于自动分割

论文地址&#xff1a;Biosensors | Free Full-Text | Feature-Based Information Retrieval of Multimodal Biosignals with a Self-Similarity Matrix: Focus on Automatic Segmentation (mdpi.com) 论文源码&#xff1a;无 期刊&#xff1a;biosensors 这篇论文提出了一种基…

redis缓存实现分布式锁原理及注意事项(附代码)

分布式锁是用于在分布式系统中对共享资源进行访问控制的一种机制&#xff0c;它可以确保在多个节点并发访问时只有一个节点能够获取到锁&#xff0c;从而保证对共享资源的操作不会发生冲突。 实现原理&#xff1a; 使用Redis缓存实现分布式锁的基本原理&#xff1a; ● SETNX…

每日一题:C语言经典例题之报数字说英文

题目描述 输入一个1到7之间的数字&#xff0c;表示星期一到星期日&#xff0c;输出相应的英文&#xff1a;Mon、Tue、Wed、Thur、Fri、Sat、Sun。 输入 输入一个1到7之间的数字。 输出 输出与数字对应的英文。 样例输入 6 样例输出 Sat 代码 #include <stdio.h> int …

kafka(六)——存储策略

存储机制 kafka通过topic作为主题缓存数据&#xff0c;一个topic主题可以包括多个partition&#xff0c;每个partition是一个有序的队列&#xff0c;同一个topic的不同partiton可以分配在不同的broker&#xff08;kafka服务器&#xff09;。 关系图 partition分布图 名称为t…

利用细粒度检索增强和自我检查提升对话式问题解答能力

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 论文标题&#xff1a;Boosting Conversational Question Answering with Fine-Grained Retrieval-Augmentation and Self-Check 论文地址&#xff1a;https://arxiv.org/abs/2403.18243 检索增强生成…

力扣53 最大子数组和 Java版本

文章目录 题目描述代码 题目描述 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组 是数组中的一个连续部分。 示例 1&#xff1a; 输入&#xff1a;nums [-2,1,-…

Echarts使用dataTool写可自定义横坐标的盒须图(箱线图)

在vue2中的完整盒须图组件代码 可自适应浏览器窗体变化&#xff0c;可自定义横坐标&#xff0c;无需写箱线图数据处理逻辑。dataTool是echarts自带的&#xff0c;无需额外安装&#xff0c;只要引入。 <template><span><div ref"BoxPlotChart" id&qu…

phpstorm 快捷键

PHPstorm最常用的快捷键&#xff0c;提高开发效率 - 知乎 (zhihu.com) 四年精华PHP技术文章整理合集——PHP框架篇 (qq.com) 四年精华PHP技术文合集——微服务架构篇 (qq.com)

程序“猿”自动化脚本(一)

1.剪贴板管理器&#x1f4cb; 您是否曾经发现自己在处理多个文本片段时忘记了复制的内容&#xff1f;有没有想过有一个工具可以跟踪您一天内复制的所有内容&#xff1f; 该自动化脚本会监视您复制的所有内容&#xff0c;将每个复制的文本无缝存储在时尚的图形界面中&#xff0c…

Python向文件里写入数据

直接上代码 name "测试" data name.encode("utf-8")# w特点&#xff1a;文件不存在则创建文件并在打开前清空 f open("db.txt", mode"wb")f.write(data)f.close()可以在 db.txt 文件里看到一句话 测试name "Testing" …

阿里云4核16G服务器可以用来做什么?

阿里云4核16G服务器可以用来做什么&#xff1f;可用来搭建游戏服务器&#xff0c;阿里云4核16G服务器10M带宽30元1个月、90元3个月&#xff0c;优惠活动 aliyunfuwuqi.com/go/youhui 阿里云4核16G服务器可以用来做什么&#xff1f;除了搭建游戏服务器&#xff0c;还可以用来哪…

167. 两数之和 II - 输入有序数组(Java)

目录 题目描述&#xff1a;输入&#xff1a;输出&#xff1a;代码实现&#xff1a;1.二分&#xff08;折半&#xff09;查找2.双指针向内缩进 题目描述&#xff1a; 给你一个下标从 1 开始的整数数组 numbers &#xff0c;该数组已按 非递减顺序排列 &#xff0c;请你从数组中找…

基于 GPIO 、Pinctl子系统、设备树的LED 驱动程序

理论部分&#xff1a; 编写思路&#xff1a; GPIO 的地位跟其他模块&#xff0c;比如 I2C 、 UART 的地方是一样的&#xff0c;要使用某个引脚&#xff0c;需要先把引脚配置为 GPIO 功能&#xff0c;这要使用 Pinctrl 子系统&#xff0c;只需要在设备 树里指定就可以。在…

力扣HOT100 - 41. 缺失的第一个正数

解题思路&#xff1a; 原地哈希 就相当于&#xff0c;让每个数字n都回到下标为n-1的家里。 而那些没有回到家里的就成了孤魂野鬼流浪在外&#xff0c;他们要么是根本就没有自己的家&#xff08;数字小于等于0或者大于nums.size()&#xff09;&#xff0c;要么是自己的家被别…

springCloud项目打包 ,maven package或install打包报错

解决思路一&#xff1a; <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.3.7.RELEASE</version></plugin><plugin>&…

【应急响应事件】记一次矿机木马事件

事情起因&#xff0c;是因为实验室有一台服务器的占用率从开机启动就是100%&#xff0c;很怀疑就是中了某种矿机木马&#xff0c;拿去挖矿了&#xff0c;然后经过师兄的不懈努力&#xff0c;终于找到了木马文件&#xff0c;给他命名为virus_sample 然后我就拿着样本去逆了 木马…

OSCP靶场--Peppo

OSCP靶场–Peppo 考点(ident枚举服务用户名ssh登陆rbash绕过 docker提权) 1.nmap扫描 ## ┌──(root㉿kali)-[~/Desktop] └─# nmap 192.168.158.60 -sV -sC -Pn --min-rate 2500 -p- Starting Nmap 7.92 ( https://nmap.org ) at 2024-04-10 09:32 EDT Nmap scan report…