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

算法很美笔记(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;而…...

C++ ——继承

体现的是代码复用的思想 1、子类继承父类&#xff0c;子类就拥有了父类的特性&#xff08;成员方法和成员属性&#xff09; 2、已存在的类被称为“基类”或者“父类”或者“超类”&#xff1b;新创建的类被称为“派生类”或者“子类” 注意&#xff1a; &#xff08;1&#…...

LeetCode 热题 100 283. 移动零

LeetCode 热题 100 | 283. 移动零 大家好&#xff0c;今天我们来解决一道经典的算法题——移动零。这道题在LeetCode上被标记为简单难度&#xff0c;要求我们将数组中的所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。下面我将详细讲解解题思路&#xff0c;…...

游戏引擎学习第116天

回顾昨天的工作 本次工作内容主要集中在游戏开发的低级编程优化&#xff0c;尤其是手动优化软件渲染。工作目的之一是鼓励开发者避免依赖外部库&#xff0c;而是深入理解代码并进行优化。当前阶段正进行SIMD&#xff08;单指令多数据&#xff09;优化&#xff0c;使用Intel推荐…...

react(9)-redux

使用CRA快速创建react项目 npx create-react-app react-redux 安装配套工具 npm i reduxjs/toolkit react-redux 启动项目 在创建项目时候会出现一个问题 You are running create-react-app 5.0.0, which is behind the latest release (5.0.1). We no longer support…...

Linux内核实时机制7 - 实时改造机理 - 软中断优化下

Linux内核实时机制7 - 实时改造机理 - 软中断优化下 https://blog.csdn.net/u010971180/article/details/145722641以下分别以Linux4.19、Linux5.4、Linux5.10、Linux5.15 展开分析,深入社区实时改造机理的软中断优化过程。https://blog.csdn.net/weixin_41028621/article/det…...

企业知识管理平台重构数字时代知识体系与智能服务网络

内容概要 现代企业知识管理平台的演进呈现出全生命周期管理与智能服务网络构建的双重特征。通过四库体系&#xff08;知识采集库、加工库、应用库、评估库&#xff09;的协同运作&#xff0c;该系统实现了从知识沉淀、结构化处理到价值释放的完整闭环。其中&#xff0c;知识图…...

大数据组件(四)快速入门实时数据湖存储系统Apache Paimon(3)

Paimon的下载及安装&#xff0c;并且了解了主键表的引擎以及changelog-producer的含义参考&#xff1a; 大数据组件(四)快速入门实时数据湖存储系统Apache Paimon(1) 利用Paimon表做lookup join&#xff0c;集成mysql cdc等参考&#xff1a; 大数据组件(四)快速入门实时数据…...

SVN把英文换中文

原文链接&#xff1a;SVN设置成中文版本 都是英文&#xff0c;换中文 Tortoise SVN 安装汉化教程(乌龟SVN) https://pan.quark.cn/s/cb6f2eee3f90 下载中文包...

Ubuntu 的RabbitMQ安装

目录 1.安装Erlang 查看erlang版本 退出命令 2. 安装 RabbitMQ 3.确认安装结果 4.安装RabbitMQ管理界面 5.启动服务并访问 1.启动服务 2.查看服务状态 3.通过IP:port 访问界面 4.添加管理员用户 a&#xff09;添加用户名&#xff1a;admin&#xff0c;密码&#xff1…...

基于WebRTC与AI大模型接入EasyRTC:打造轻量级、高实时、强互动的嵌入式音视频解决方案

随着物联网和嵌入式技术的快速发展&#xff0c;嵌入式设备对实时音视频通信的需求日益增长。然而&#xff0c;传统的音视频解决方案往往存在体积庞大、实时性差、互动体验不佳等问题&#xff0c;难以满足嵌入式设备的资源限制和应用场景需求。 针对以上痛点&#xff0c;本文将介…...

QML 实现一个动态的启动界面

QML 实现一个动态的启动界面 一、效果查看二、源码分享三、所用到的资源下载 一、效果查看 二、源码分享 工程结构 main.qml import QtQuick import QtQuick.Controls import QtQuick.Dialogs import Qt.labs.platformWindow {id:windowwidth: 640height: 400visible: truetit…...

智能预警系统标准化处理流程

在当今数字化时代,IT系统的稳定运行对企业的业务连续性至关重要。为了及时发现和响应系统异常,构建智能预警系统已成为许多企业的当务之急。但仅仅拥有预警系统还不够,我们还需要一套标准化的处理流程,确保问题能够高效、有序地得到解决。 © ivwdcwso (ID: u012172506) 一…...

Unity游戏制作中的C#基础(4)数组声明和使用

一、数组的声明 在 C# 中&#xff0c;声明数组有多种方式&#xff0c;每种方式都有其适用的场景&#xff0c;下面为你逐一详细介绍&#xff1a; 1. 直接初始化声明 这种方式直观且便捷&#xff0c;在声明数组的同时就为其赋初值&#xff0c;让数组从诞生之初就拥有了具体的数据…...

tailwindcss学习03

01 入门 02 vue中接入 03 工具类优先 准备 vue.svg <svg viewBox"0 0 40 40" xmlns"http://www.w3.org/2000/svg"> <defs> <linearGradient x1"50%" y1"0%" x2"50%" y2"100%" id"a"&…...

QML Component 与 Loader 结合动态加载组件

在实际项目中&#xff0c;有时候我们写好一个组件&#xff0c;但不是立即加载出来&#xff0c;而是触发某些条件后才动态的加载显示出来&#xff0c;当处理完某些操作后&#xff0c;再次将其关闭掉&#xff1b; 这样的需求&#xff0c;可以使用 Component 包裹着组件&#xff…...

Visual studio 2022 将打开文件的方式由单击改为双击

1. 打开vs2022&#xff0c;选择Tools -> Options打开Options设置页面 2. 在左侧依次展开Environment, 选择Tabs and Windows 3. 在右侧面板往下拖拽滚动条&#xff0c;找到Preview Tab section, unchecked "Preview selected files in Solution Explorer (Altclick t…...

网络工程师 (49)UDP协议

前言 UDP协议&#xff0c;即用户数据报协议&#xff08;User Datagram Protocol&#xff09;&#xff0c;是一种无连接的、不可靠的、面向报文的传输层通信协议。 一、基本特点 无连接性&#xff1a;UDP在发送数据之前不需要与目标设备建立连接&#xff0c;也无需在数据发送结束…...

了解大数据

一、大数据的特点&#xff1a; 1.大量 2.高速 3.多样 结构化数据和非结构化数据 4.低价值密度 二、大数据的应用场景&#xff1a;视频推荐、电商推荐等 三、大数据的技术发展脉络 阶段1&#xff1a;单机时代 阶段2&#xff1a;大数据时代-分布式处理 阶段3&#xff1a;实…...

命令模式

1. 命令模式简介 命令模式(Command Pattern)是一种行为型设计模式,它将一个请求封装为一个对象,从而使您可以用不同的请求对客户进行参数化、对请求排队或记录请求日志,以及支持可撤销的操作。命令模式的核心思想是将操作和操作的执行者解耦,使得操作可以独立于执行者进…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

Spring是如何解决Bean的循环依赖:三级缓存机制

1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间‌互相持有对方引用‌,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈

在日常iOS开发过程中&#xff0c;性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期&#xff0c;开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发&#xff0c;但背后往往隐藏着系统资源调度不当…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

uniapp手机号一键登录保姆级教程(包含前端和后端)

目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号&#xff08;第三种&#xff09;后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...