当前位置: 首页 > article >正文

算法很美笔记(Java)——动态规划

解重叠子问题(当前解用到了以前求过的解)

形式:记忆型递归或递推(dp)

动态规划本质是递推,核心是找到状态转移的方式,也就是填excel表时的逻辑(填的方式),而后代码就按填表的逻辑写即可

可以先写递归解法,发现有很多重叠子问题时,再改dp

递归是从大规模到小规模,记忆型递归或dp都是小规模到大规模

大多数情况,题中要求什么,dp的值就代表什么,比如求最大长度,dp值就是最大长度

01背包问题

使用dfs,分为选和不选

递归

static int[] wi = {1,5,10,50,100,500};static int[] vi = {1,5,1,0,10,2};public static int t1(int w,int curr) {if (w <= 0)  return 0;if (curr == wi.length) return 0;if (w < wi[curr]) {//            重量不够,选不上了return t1(w,curr++);} else {
//        不选int choice1 = t1(w,curr++);//         选int choice2 =  vi[curr] + t1(w - wi[curr],curr++);
//            返回的是选择树当前层以下的所有层的最优解
//            与本层的选择无关,所以不会出现因为不知道选还是不选比较大而导致的w混乱return Math.max(choice1,choice2);}}

dp

因为后面的行需要借助第一行的值填,所以先初始化第一行,再填后面的

物品编号也就是当前可选什么物品,编号以前的物品都能选,比如编号2,则第1~3个物品都能选。但是我们因为是借助前面填过的数据填,所以实际上,只需要考虑当前编号的物品的选与不选,而编号以前的物品通过“借助前面填过的数据填”时就已经选上了。

价值计算= 当前物品价值 +(上一行,可用重量)----->选

              =(上一行,可用重量)----->不选

eg:

表格(2,3),当前容量为3,物品重量为3,要的起,所以分为选与不选。

选:价值 = 4 +(1,0 )= 4----->选

               =(1,3 )= 5----->不选

因为每格需要借助其他格的值填,所以不能只考虑w的容量,而是要考虑0~w 之间的所有容量,而最终所求,是右下角的那个值。因为我们计算的是考虑所有物品的情况下(最后一行),容量为w(最后一列)的最大利润

static int[] wi = {1,5,10,50,100,500};static int[] vi = {1,5,1,0,10,2};public static int _01bag(int w) {
//        二维数组存储数据
//        重量0~wint[][] arr = new int[wi.length][w + 1];
//        初始化第一行数据for (int j = 0; j < w + 1; j++) {if (j >= wi[0]) {
//                要的起arr[0][j] = vi[0];} else {
//                要不起arr[0][j] = 0;}}
//利用前一行填当前行for (int i = 1; i < wi.length; i++) {for (int j = 0; j < w + 1; j++) {if (j >= wi[i]) {
//                要的起
//                    要int get = vi[i] + arr[i - 1][j - wi[i]];
//                    不要int noGet = arr[i - 1][j];arr[i][j] = Math.max(get,noGet);} else {
//                要不起arr[i][j] = arr[i - 1][j];}}}
//        取右下角作为结果return arr[wi.length - 1][w];}

完全背包

比01背包多了个条件:每种物品可以挑选任意多件。

dp

仍然初始化第一行,用以供给后面计算

虽然一个物品可以选多次,但是我们还是只分为选和不选

当不选时,思路和01背包相同(剩余重量在上一行中寻找最优解)

当选时,选一个后,剩余重量在同行中寻找最优解。

因为只要是填过的就是已经找到最优解的了,同一个物品,我们只需要选一次,至于最终要选几次,交给同行的最优解来解决

钢条切割

第一刀可以切1+9、2+8、3+7……

1+9的第二刀切9,可以切成1+8、2+7……

2+8的第二刀切8,可以切成1+7、2+6……

也就是,固定前面的一段,切后面一段

因为如果两段都切会导致有很多重复结果比如2+8-->1+1 + 2+6和3+7-->1+2 + 1+6

因为是固定前面的一段,切后面一段,所以固定的的那一段长度可以直接得到价值,而只有后面那段价值不确定

递归

每切一刀就是一个递归,因为有不同切法,所以是for循环(控制切法)里写递归(控制刀数)

这样他们之间求max,就是结果(类似01背包问题的max,只不过01背包同层间都是两种选择,而本问题同层之间是不止两种)

static int[] v = {1 , 5 , 8 , 16 , 10 , 17 , 17 , 20 , 24 , 30};public static int cut(int x) {if (x == 0) return 0;
//        每刀切的长度1~10int maxSum = 0;for (int i = 1; i <= x; i++) {maxSum = Math.max(maxSum,(v[i-1] + cut(x - i)));}return maxSum;}

记忆型递归

这里会不止一次递归f(1)、f(2)……f(10),显然重复计算了

想改成只算一次,则用一个数组把这些值给记下来,当需要用的时候,如果有就直接用,没有就计算再存起来,以供后面计算使用

代码与直接递归类似

dp

画excel表为一个长度-价值最优表,不同长度的钢条对应不同价值

思路中,组合中第二段长度价值不确定,所以我们画了最优表,第二段价值直接取就行

最后求得长度为10的钢条的最大价值,return 价值

static int[] v = {1 , 5 , 8 , 16 , 10 , 17 , 17 , 20 , 24 , 30};public static int cut() {int[] sum = new int[11];sum[0] = 0;sum[1] = 1;for (int i = 3; i < 11; i++) {
//            curr初始为钢条不切,直接卖int curr = v[i - 1];for (int j = 1; j < i; j++) {int temp = v[j - 1] + sum[i - j];curr = Math.max(curr,temp);}sum[i] = curr;}return sum[10];}

数字三角形

The Triangle - POJ 1163 - Virtual Judge

在数字三角形中寻找一条从顶部到底边的路径,使得路径上所经过的数字之和最大。路径上的每一步都只能往左下或 右下走。只需要求出这个最大和即可,不必给出具体路径。三角形的行数大于1小于等于100,数字为 0 - 99输入格式:5 //表示三角形的行数 接下来输入三角形73 88 1 02 7 4 44 5 2 6 5
要求输出最大和

只能选左下,右下,而不是一层内可以随便选,所以无法一次性确定选什么最大,所以无法用贪心

那么就使用dfs把所有情况都列出来

可以看到,dfs会重复算中间的数,比如算第二层的3和8时,3算了f(1),8也算了f(1),所以用dp

从下往上填,最后一行没得选,直接初始化,其他行,找加起来更大的填上

static int[][] v = {{7},{3,8},{8,1,0},{2,7,4,4},{4,5,2,6,5},};public static int Triangle() {int[][] arr = new int[5][5];
//        System.out.println(arr[3].length);
//        初始化一行for (int i = 0; i < 5; i++) {arr[4][i] = v[4][i];}
//        填其他行for (int i = arr.length - 2; i >= 0; i--) {
//            列for (int j = 0; j < i + 1; j++) {arr[i][j] = Math.max(v[i][j] + arr[i+1][j],v[i][j] + arr[i+1][j+1]);}}return arr[0][0];}

最长公共子序列(LCS)

子数组只能像截取一段这样,是紧凑的

而子序列可以跳着来,只要前后顺序一致就行

比如AB34CA1BC2 则输出ABC

找出全部公共子序列,然后求max

有串S1 = AB34,S2 = A1BC2

让S1的每一个字母都作为一个子序列的开头

eg:让A作为开头,则去S2里找A,找到了的话,通过将后面未处理的序列进行递归和字符串拼接将后续子序列拼接出来。没找到则不用处理,这样max的时候就不会被取

这样处理完A开头的子序列后,处理B开头的子序列……

将这些子序列取长度max返回

用ArrayList存结果

for i :S1每个开头

        for j:S2 找相同字母

                找到了:当前字母+递归(剩余子串)

        if(上一个子序列.size()<当前子序列.size())res = 当前子序列

public static ArrayList<Character> str(String s1,String s2) {
//        让s1的,每一个字母开头ArrayList<Character> endRes = new ArrayList<>();for (int i = 0; i < s1.length(); i++) {ArrayList<Character> res = new ArrayList<>();
//            去s2找匹配的for (int j = 0; j < s2.length(); j++) {if (s1.charAt(i) == s2.charAt(j)) {res.add(s1.charAt(i));res.addAll(str(s1.substring(i + 1),s2.substring(j + 1)));break;}}if (res.size() > endRes.size()) {endRes = res;}}return endRes;}

最长上升子序列问题


有一个长为n的数列a0,a1,...,a(n-1)。请求出这个序列中最长的上升子序列的长度。上升子序列指的是对于任意的i&lt;j都满足ai&lt;aj的子序列。1≤n≤10000≤ai≤1000000输入n=5
a={4,2,3,1,5}
输出3(注:2,3,5)

因为是子序列,所以可以跳着取

暴力法

类似上一题的思路

以每一个数字开头,遍历向后找比这个数字大的数字,剩余数字用递归找

而后所有子序列求max 

dp

dp的每个值代表:以这个数字作为结尾,由它前面的数字组成的最长子序列的长度

curr是当前数字,

与前面每个数字做比较,自己较大,则curr的一个dp值等于 前面的数字的dp值+1,自己较小则urr的一个dp值等于 1(子序列只有自己,长度就是1)

再与更前面的数字作比较,求出一个dp值

…………

等与前面的每个数字作比较求出dp值后,取最大的dp值为最终dp值

求完所有dp值后,取最大的值作为结果返回

public static int maxLen(int[] a) {if (a.length == 0) return 0;int[] dp = new int[a.length];dp[0] = 1;for (int i = 1; i < dp.length; i++) {
//            子序列只有自己的时候的lengthint res = 1;
//            与前面的元素作比较for (int j = i - 1; j >= 0 ; j--) {
//                较小,子序列length就是1
//                较大if (a[j] < a[i]) {int temp = dp[j] + 1;
//                    取maxif (res < temp) {res = temp;}}}dp[i] = res;}return max(dp);}public static int max(int[] dp) {int maxVal = 0;for (int i = 0; i < dp.length; i++) {if (dp[i] > maxVal) {maxVal = dp[i];}}return maxVal;}public static void main(String[] args) {System.out.println(maxLen(new int[]{4,2,3,1,5}));}

相关文章:

算法很美笔记(Java)——动态规划

解重叠子问题&#xff08;当前解用到了以前求过的解&#xff09; 形式&#xff1a;记忆型递归或递推&#xff08;dp&#xff09; 动态规划本质是递推&#xff0c;核心是找到状态转移的方式&#xff0c;也就是填excel表时的逻辑&#xff08;填的方式&#xff09;&#xff0c;而…...

Jest单元测试

由于格式和图片解析问题&#xff0c;可前往 阅读原文 前端自动化测试在提高代码质量、减少错误、提高团队协作和加速交付流程方面发挥着重要作用。它是现代软件开发中不可或缺的一部分&#xff0c;可以帮助开发团队构建可靠、高质量的应用程序 单元测试&#xff08;Unit Testi…...

《Stable Diffusion绘画完全指南:从入门到精通的Prompt设计艺术》-配套代码示例

第一章&#xff1a;模型加载与基础生成 1.1 基础模型加载 from diffusers import StableDiffusionPipeline import torch# 加载SD 1.5基础模型&#xff08;FP32精度&#xff09; pipe StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5",…...

OnlyOffice:前端编辑器与后端API实现高效办公

OnlyOffice&#xff1a;前端编辑器与后端API实现高效办公 一、OnlyOffice概述二、前端编辑器&#xff1a;高效、灵活且易用1. 完善的编辑功能2. 实时协作支持3. 自动保存与版本管理4. 高度自定义的界面 三、后端API&#xff1a;管理文档、用户与权限1. 轻松集成与定制2. 实时协…...

springboot多实例部署时,@Scheduled注释的方法重复执行

问题&#xff1a;springboot多实例部署时&#xff0c;Scheduled注释的方法重复执行 在 Spring Boot 中要实现 Redis 的SET NX EX命令&#xff0c;可以借助 Spring Data Redis 来完成。SET NX EX命令用于在键不存在时设置键值对&#xff0c;并同时设置过期时间。 <dependen…...

coco格式

COCO&#xff08;Common Objects in Context&#xff09;格式是一种广泛用于图像识别和分割任务的数据格式&#xff0c;尤其是在目标检测、语义分割等任务中。COCO格式的核心包括以下几个部分&#xff1a; images: 包含图像的基本信息&#xff08;如文件名、大小、ID等&#x…...

骶骨神经

骶骨肿瘤手术后遗症是什么_39健康网_癌症 [健康之路]匠心仁术&#xff08;七&#xff09; 勇闯禁区 骶骨肿瘤切除术...

Nacos学习(二)——继承Feign与Config中心

目录 一、集成Feign (一)基础用法 1.添加openfeign依赖 2. 开启openFeign注解扫描 3.创建ProviderService接口 4.修改ConsumerController (二)OpenFeign日志配置 (三)参数传递 1.参数传递的问题 2.参数传递的方式 2.1URL路径传参 2.2URL上拼接参数 2.3body传参 …...

计算机网络安全之一:网络安全概述

1.1 网络安全的内涵 随着计算机和网络技术的迅猛发展和广泛普及&#xff0c;越来越多的企业将经营的各种业务建立在Internet/Intranet环境中。于是&#xff0c;支持E-mail、文件共享、即时消息传送的消息和协作服务器成为当今商业社会中的极重要的IT基础设施。然而&#xff0…...

未来SLAM的研究方向和热点

SLAM&#xff08;Simultaneous Localization and Mapping&#xff09;是同时定位与地图构建的缩写&#xff0c;指的是机器人或设备在一个未知环境中一边进行自我定位&#xff0c;一边构建出环境的地图。SLAM广泛应用于机器人、自动驾驶、无人机等领域&#xff0c;涉及多个研究方…...

DuodooBMS源码解读之 purchase_change 模块

采购变更模块用户使用手册 一、模块概述 本扩展模块主要用于处理采购变更相关业务&#xff0c;包括采购变更单的创建、展示以及将采购变更信息导出为 Excel 文件等功能。以下将详细介绍该模块的具体使用方法。 二、模块功能及使用方法 &#xff08;一&#xff09;采购变更单…...

uniapp中引入Vant Weapp的保姆级教学(包含错误处理)

废话不多说&#xff0c;直接上方法&#xff0c;网上的教学好多都是错误的 1.安装vant weapp 在Hbuilder的终端&#xff0c;输入以下代码 npm install vant/weapp -S --production 2.新建wxcomponents文件夹 在项目的跟目录新建一个“wxcomponents’文件夹&#xff0c;与app.…...

Effective C++ 读书笔记(十二)

条款三十四&#xff1a;区分接口继承和实现继承 public继承由两部分组成&#xff1a;函数接口继承和函数实现继承。这两者的差异很像函数声明和函数定义之间的差异。 作为类的设计者&#xff0c;我们有时希望派生类只继承成员函数的接口&#xff08;也就是函数声明&#xff0…...

【卡梅德生物】构建噬菌体文库与噬菌体展示文库构建服务新探索

在生命科学与生物技术快速发展的当下&#xff0c;抗体文库构建、构建噬菌体文库以及噬菌体展示文库构建服务在生物医药研发领域中占据着举足轻重的地位。它们不仅是基础研究的重要工具&#xff0c;更是推动抗体药物开发、疾病诊断技术进步的关键力量。 构建噬菌体文库是整个技…...

【JavaScript】《JavaScript高级程序设计 (第4版) 》笔记-Chapter19-表单脚本

十九、表单脚本 表单脚本 JavaScript 较早的一个用途是承担一部分服务器端表单处理的责任。虽然 Web 和 JavaScript 都已经发展了很多年&#xff0c;但 Web 表单的变化不是很大。由于不能直接使用表单解决问题&#xff0c;因此开发者不得不使用JavaScript 既做表单验证&#xf…...

C++STL容器之map

1.介绍 map是 C 标准模板库&#xff08;STL&#xff09;中的一个关联容器&#xff0c;用于存储键值对&#xff08;key-value pairs&#xff09;。map中的元素是按照键&#xff08;key&#xff09;进行排序的&#xff0c;并且每个键在容器中是唯一的。map通常基于红黑树&#xf…...

基于Nanopi duo2的WiFi智能摄像头

1.固件包烧录 https://wiki.friendlyelec.com/wiki/index.php/NanoPi_Duo2/zh#.E8.BF.9E.E6.8E.A5WiFi 固件包链接以及烧录工具都在上面链接中 烧录过程 使用读卡器将SD卡插入到电脑,然后打开烧录工具 2.通过串口工具连接板子使其连接WiFi 对应的串口工具,就是这个HyperT…...

Java 内存区域详解

1 常见面试题 1.1 基本问题 介绍下Java内存区域&#xff08;运行时数据区&#xff09;Java对象的创建过程&#xff08;五步&#xff0c;建议能够默写出来并且要知道每一步虚拟机做了什么&#xff09;对象的访问定位的两种方式&#xff08;句柄和直接指针两种方式&#xff09;…...

MyBatis框架详解与核心配置解读

目录 前言 一、MyBatis框架概述 1.1 什么是MyBatis 1.2 MyBatis的优点 二、MyBatis的使用入门与案例 2.1 MyBatis核心配置文件&#xff08;mybatis-config.xml&#xff09; 2.2 XML映射文件&#xff08;UserMapper.xml&#xff09; 三、MyBatis的常用注解及其用法 3.1…...

Windows 快速搭建C++开发环境,安装C++、CMake、QT、Visual Studio、Setup Factory

安装C 简介 Windows 版的 GCC 有三个选择&#xff1a; CygwinMinGWmingw-w64 Cygwin、MinGW 和 mingw-w64 都是在 Windows 操作系统上运行的工具集&#xff0c;用于在 Windows 环境下进行开发和编译。 Cygwin 是一个在 Windows 上运行的开源项目&#xff0c;旨在提供类Uni…...

GO系列-IO 文件操作

os io 判断文件是否存在 func fileExist(filePath string) (bool, error) {_, err : os.Stat(filePath)if err nil {return true, nil}if os.IsNotExist(err) {return false, nil}return false, &CheckFileExistError{filePath} } 读取文件内容 func readFileContext(…...

Unity Excel导表工具转Lua文件

思路介绍 借助EPPlus读取Excel文件中的配置数据&#xff0c;根据指定的不同类型的数据配置规则来解析成对应的代码文本&#xff0c;将解析出的字符串内容写入到XXX.lua.txt文件中即可 EPPlus常用API //命名空间 using OfficeOpenXml;//Excel文件路径 var fileExcel new File…...

Helix——Figure 02发布通用人形机器人控制的VLA:一组神经网络权重下的快与慢双系统,让两个机器人协作干活

前言 过去一周&#xff0c;我花了很大的心思、力气&#xff0c;把deepseek的GRPO、MLA算法的代码解析通透&#xff0c;比如GRPO与PPO的详细对比&#xff0c;再比如MLA中&#xff0c;图片 公式 代码的一一对应 2.20日晚&#xff0c;无意中刷到figure 02发布Helix的一个演示视频…...

汽车自动驾驶辅助L2++是什么?

自动驾驶辅助级别有哪些&#xff1f; 依照SAE&#xff08;SAE International&#xff0c;Society of Automotive Engineers国际自动机工程师学会&#xff09;的标准&#xff0c;大致划分为6级&#xff08;L0-L5&#xff09;&#xff1a; L0人工驾驶&#xff1a;即没有驾驶辅助…...

进程的介绍--进程状态/切换

1.冯 • 诺依曼体系结构 1.1 体系结构 冯•诺依曼结构也称普林斯顿结构&#xff0c;是一种将程序指令存储器和数据存储器合并在一起的存储器结构。数学家冯•诺依曼提出了计算机制造的三个基本原则&#xff0c;即采用二进制逻辑、程序存储执行以及计算机由五个部分组成&#x…...

goby(蓝队红队版)扫描工具扫描使用时候报错解决方法

1.Goby 是一款开源的网络安全扫描工具&#xff0c;主要用于漏洞扫描、资产发现和信息收集。它旨在帮助安全研究人员、渗透测试人员和红队成员自动化和简化网络漏洞扫描过程。Goby 提供了多种功能&#xff0c;能够在大量的目标中高效地识别出潜在的安全漏洞。 2.今天在官网下载…...

Word文档中插入的图片不能完整显示

在在Word文档中插入图片&#xff0c;只显示图片最下面的一小部分。 将“固定值”更改为“单倍行距”...

模电知识点总结(6)

1.选取频率高于1000Hz的信号时&#xff0c;可选用高通滤波器&#xff1b;抑制50Hz的交流干扰时&#xff0c;可选用带阻滤波器如果希望抑制500Hz以下的信号&#xff0c;可选用高通滤波器。 2.有用信号频率高于1000Hz&#xff0c;可选用高通滤波器&#xff1b;希望抑制50Hz的交流…...

Linux操作系统4-进程间通信4(共享内存原理,创建,查看,命令)

上篇文章&#xff1a;Linux操作系统4-进程间通信3&#xff08;基于管道的进程池设计&#xff09;-CSDN博客 本篇Gitee代码&#xff1a;myLerningCode/l24 橘子真甜/Linux操作系统与网络编程学习 - 码云 - 开源中国 (gitee.com) 本篇重点&#xff1a;使用共享内存来实现两个进程…...

Grok 使用指南

文章来源&#xff1a;Grok 漫游指南 | xAI Docs 欢迎&#xff01;在本指南中&#xff0c;我们将引导您了解使用 xAI API 的基础知识。 #第 1 步&#xff1a;创建 xAI 帐户 您需要一个 xAI 帐户才能访问 xAI API。在此处注册帐户。 创建账户后&#xff0c;您需要为其加载积分…...