算法沉淀——动态规划之其它背包问题与卡特兰数(leetcode真题剖析)

在这里插入图片描述

算法沉淀——动态规划之其它背包问题与卡特兰数

  • 二维费用的背包问题
    • 01.一和零
    • 02.盈利计划
  • 似包非包
    • 组合总和 Ⅳ
  • 卡特兰数
    • 不同的二叉搜索树

二维费用的背包问题

01.一和零

题目链接:https://leetcode.cn/problems/ones-and-zeroes/

给你一个二进制字符串数组 strs 和两个整数 mn

请你找出并返回 strs 的最大子集的长度,该子集中 最多m0n1

如果 x 的所有元素也是 y 的元素,集合 x 是集合 y子集

示例 1:

输入:strs = ["10", "0001", "111001", "1", "0"], m = 5, n = 3
输出:4
解释:最多有 5 个 0 和 3 个 1 的最大子集是 {"10","0001","1","0"} ,因此答案是 4 。
其他满足题意但较小的子集包括 {"0001","1"} 和 {"10","1","0"} 。{"111001"} 不满足题意,因为它含 4 个 1 ,大于 n 的值 3 。

示例 2:

输入:strs = ["10", "0", "1"], m = 1, n = 1
输出:2
解释:最大的子集是 {"0", "1"} ,所以答案是 2 。

提示:

  • 1 <= strs.length <= 600
  • 1 <= strs[i].length <= 100
  • strs[i] 仅由 '0''1' 组成
  • 1 <= m, n <= 100

思路

问题转化为二维费用的01背包问题:

  1. 状态表示:
    • dp[i][j][k] 表示从前 i 个字符串中挑选,字符 0 的个数不超过 j,字符 1 的个数不超过 k,所有的选法中,最大的长度。
  2. 状态转移方程:
    • 根据最后一步的状况,分两种情况讨论:
      • 不选第 i 个字符串:相当于去前 i - 1 个字符串中挑选,并且字符 0 的个数不超过 j,字符 1 的个数不超过 k。此时的最大长度为 dp[i][j][k] = dp[i - 1][j][k]
      • 选择第 i 个字符串:接下来在前 i - 1 个字符串中挑选,字符 0 的个数不超过 j - a,字符 1 的个数不超过 k - b 的最大长度,然后在这个长度后面加上字符串 i。此时 dp[i][j][k] = dp[i - 1][j - a][k - b] + 1。需要特判这种状态是否存在。
    • 综上,状态转移方程为:dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - a][k - b] + 1)
  3. 初始化:
    • 当没有字符串的时候,没有长度,因此初始化为 0
  4. 填表顺序:
    • 保证第一维的循环从小到大即可。
  5. 返回值:
    • 根据状态表示,返回 dp[l][m][n]

代码

class Solution {
public:int findMaxForm(vector<string>& strs, int m, int n) {int l=strs.size();vector<vector<vector<int>>> dp(l+1,vector<vector<int>>(m+1,vector<int>(n+1)));for(int i=1;i<=l;i++){int a=0,b=0;for(char ch:strs[i-1])if(ch=='0') a++;else b++;for(int j=m;j>=0;j--)for(int k=n;k>=0;k--){dp[i][j][k]=dp[i-1][j][k];if(j>=a&&k>=b) dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-a][k-b]+1);}}return dp[l][m][n];}
};

02.盈利计划

题目链接:https://leetcode.cn/problems/profitable-schemes/

集团里有 n 名员工,他们可以完成各种各样的工作创造利润。

i 种工作会产生 profit[i] 的利润,它要求 group[i] 名成员共同参与。如果成员参与了其中一项工作,就不能参与另一项工作。

工作的任何至少产生 minProfit 利润的子集称为 盈利计划 。并且工作的成员总数最多为 n

有多少种计划可以选择?因为答案很大,所以 返回结果模 10^9 + 7 的值

示例 1:

输入:n = 5, minProfit = 3, group = [2,2], profit = [2,3]
输出:2
解释:至少产生 3 的利润,该集团可以完成工作 0 和工作 1 ,或仅完成工作 1 。
总的来说,有两种计划。

示例 2:

输入:n = 10, minProfit = 5, group = [2,3,5], profit = [6,7,8]
输出:7
解释:至少产生 5 的利润,只要完成其中一种工作就行,所以该集团可以完成任何工作。
有 7 种可能的计划:(0),(1),(2),(0,1),(0,2),(1,2),以及 (0,1,2) 。

提示:

  • 1 <= n <= 100
  • 0 <= minProfit <= 100
  • 1 <= group.length <= 100
  • 1 <= group[i] <= 100
  • profit.length == group.length
  • 0 <= profit[i] <= 100

思路

  1. 状态表示:
    • dp[i][j][k] 表示从前 i 个计划中挑选,总人数不超过 j,总利润至少为 k,有多少种选法。
  2. 状态转移方程:
    • 根据最后一位的元素,有两种选择策略:
      • 不选第 i 位置的计划:此时只能在前 i - 1 个计划中挑选,总人数不超过 j,总利润至少为 k。此时有 dp[i - 1][j][k] 种选法。
      • 选择第 i 位置的计划:在前 i - 1 个计划中挑选的限制变成了,总人数不超过 j - g[i],总利润至少为 max(0, k - p[i])。此时有 dp[i - 1][j - g[i]][max(0, k - p[i])] 种选法。
    • 注意特殊情况:
      • 如果 j - g[i] < 0,说明人数过多,状态不合法,舍去。
      • 对于 k - p[i] < 0,说明利润太高,但问题要求至少为 k,因此将其取 max(0, k - p[i])
    • 综上,状态转移方程为:dp[i][j][k] = dp[i - 1][j][k] + dp[i - 1][j - g[i]][max(0, k - p[i])]
  3. 初始化:
    • 当没有任务时,利润为 0。在这种情况下,无论人数限制为多少,都能找到一个「空集」的方案。因此初始化 dp[0][j][0]1,其中 0 <= j <= n
  4. 填表顺序:
    • 根据状态转移方程,保证 i 从小到大即可。
  5. 返回值:
    • 根据状态表示,返回 dp[l][m][n],其中 l 表示计划数组的长度。

代码

class Solution {const int MOD=1e9+7;
public:int profitableSchemes(int n, int m, vector<int>& group, vector<int>& profit) {int l = group.size();vector<vector<vector<int>>> dp(l+1,vector<vector<int>>(n+1,vector<int>(m+1)));for(int j=0;j<=n;j++) dp[0][j][0]=1;for(int i=1;i<=l;i++)for(int j=0;j<=n;j++)for(int k=0;k<=m;k++){dp[i][j][k]=dp[i-1][j][k];if(j>=group[i-1]) dp[i][j][k]+=dp[i-1][j-group[i-1]][max(0,k-profit[i-1])];dp[i][j][k]%=MOD;}return dp[l][n][m];}   
};

似包非包

组合总和 Ⅳ

题目链接:https://leetcode.cn/problems/combination-sum-iv/

给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。

题目数据保证答案符合 32 位整数范围。

示例 1:

输入:nums = [1,2,3], target = 4
输出:7
解释:
所有可能的组合为:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)
请注意,顺序不同的序列被视作不同的组合。

示例 2:

输入:nums = [9], target = 3
输出:0

提示:

  • 1 <= nums.length <= 200
  • 1 <= nums[i] <= 1000
  • nums 中的所有元素 互不相同
  • 1 <= target <= 1000

思路

注意这里题目意思容易混淆概念,其实这里是一个排列问题而并非组合问题,所以应该是普通的动态规划问题

  1. 状态表示:
    • dp[i] 表示总和为 i 时,一共有多少种排列方案。
  2. 状态转移方程:
    • 对于 dp[i],根据最后一个位置划分,选择数组中的任意一个数 nums[j],其中 0 <= j <= n - 1
    • nums[j] <= i 时,排列数等于先找到 i - nums[j] 的方案数,然后在每一个方案后面加上一个数字 nums[j]
    • 因为有很多个 j 符合情况,状态转移方程为:dp[i] += dp[i - nums[j]],其中 0 <= j <= n - 1
  3. 初始化:
    • 当和为 0 时,我们可以什么都不选,即「空集」一种方案,因此 dp[0] = 1
  4. 填表顺序:
    • 根据状态转移方程,从左往右填表。
  5. 返回值:
    • 根据状态表示,返回 dp[target] 的值。

代码

class Solution {
public:int combinationSum4(vector<int>& nums, int target) {vector<double> dp(target+1);dp[0]=1;for(int i=1;i<=target;i++)for(int& x:nums)if(x<=i) dp[i]+=dp[i-x];return dp[target];}
};

卡特兰数

不同的二叉搜索树

题目链接:https://leetcode.cn/problems/unique-binary-search-trees/

给你一个整数 n ,求恰由 n 个节点组成且节点值从 1n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。

示例 1:

输入:n = 3
输出:5

示例 2:

输入:n = 1
输出:1

提示:

  • 1 <= n <= 19

思路

  1. 状态表示:
    • dp[i] 表示当结点数量为 i 个时,一共有多少颗 BST。
  2. 状态转移方程:
    • 对于 dp[i],选择每一个结点 j 作为头结点,分析不同头结点的 BST 数量。
    • 根据 BST 的定义,j 号结点的左子树的结点编号在 [1, j-1] 之间,有 j-1 个结点,右子树的结点编号在 [j+1, i] 之间,有 i-j 个结点。
    • 因此,j 号结点作为头结点的 BST 种类数量为 dp[j-1] * dp[i-j]
    • 综合每一个可能的头结点,状态转移方程为:dp[i] += dp[j-1] * dp[i-j],其中 1 <= j <= i
  3. 初始化:
    • dp[0] 表示空树,也是一颗二叉搜索树,因此 dp[0] = 1
    • 针对 i 从 1 开始的情况,需要通过 dp[j-1] * dp[i-j] 来计算。
  4. 填表顺序:
    • 从左往右填表,保证每一步都有所依赖的子问题的解。
  5. 返回值:
    • 返回 dp[n] 的值,表示结点数量为 n 时的 BST 种类数量。

代码

class Solution {
public:int numTrees(int n) {vector<int> dp(n+1);dp[0]=1;for(int i=1;i<=n;i++)for(int j=1;j<=i;j++)dp[i]+=dp[j-1]*dp[i-j];return dp[n];}
};

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

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

相关文章

【网络】主机连接 TCP 三次握手

【网络】主机连接 TCP 三次握手 一、TCP连接3次握手二、TCP连接4次挥手三、为什么tcp要三次握手&#xff0c;两次行不四、为什么TCP挥手需要4次五、Netstat命令的连接状态包括:六、练习题 一、TCP连接3次握手 1、建立连接的时候是3次握手&#xff0c;客户端向服务器端发送SYN&…

数据结构界的终极幻神----树

目录 一.数的概念和分类 种类 二.重点概念 哈希树: 二叉树的线索化 什么是线索化 为什么要线索化 特殊的查找树 完全二叉树 三.手撕完全二叉树(堆) 重点讲解 向上搜索算法 向下搜索算法 一.数的概念和分类 树&#xff08;tree&#xff09;是包含 n(n≥0) [2] 个节…

3Dmax中VR渲染太阳光渲染参数怎么设置?渲染100云渲染助力

我们用3Dmax建模时一些场景会用到太阳光&#xff0c;那么渲染参数是如何设置的呢&#xff1f; 我们一起来看看&#xff0c;直接上图 以上就是详细的参数设置&#xff0c;大家可以用做参考&#xff0c;如果本地渲染慢的朋友可以考虑使用云渲染100 机器多&#xff0c;渲染稳定不…

基于51单片机的公交ic卡系统设计

目 录 摘 要 I Abstract II 引 言 1 1 总体方案设计 3 1.1 方案选择 3 1.2 硬件选择 3 1.3 系统工作原理 4 1.4 总体方案确定 5 2 系统硬件电路设计 6 2.1 主控模块电路设计 6 2.2 电源电路设计 8 2.3 显示电路模块设计 8 2.4 报警模块电路设计 10 2.5 RC522刷卡模块 10 2.6 独…

下属OKR与上级OKR对齐时,有几种方法?

下属的OKR&#xff08;Objectives and Key Results&#xff0c;即目标与关键成果&#xff09;与上级的OKR对齐&#xff0c;是确保组织目标一致性和团队协同工作的关键步骤。以下是几种常用的对齐方法&#xff1a; 直接映射法&#xff1a;下属的OKR直接反映并支撑上级的OKR。例如…

【二】【SQL Server】如何运用SQL Server中查询设计器通关数据库期末查询大题

教学管理系统201703153 教学管理系统数据库展示 成绩表展示 课程表展示 学生表展示 院系表展示 一、基本操作 设置复合主键 设置其他表的主键 设置字段取值范围 二、简单操作 第一题 第二题 第三题 第四题 结尾 最后&#xff0c;感谢您阅读我的文章&#xff0c;希望这些内容能…

(黑马出品_04)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式

&#xff08;黑马出品_04&#xff09;SpringCloudRabbitMQDockerRedis搜索分布式 微服务技术异步通信 今日目标1.初识MQ1.1.同步和异步通讯1.1.1.同步通讯1.1.2.异步通讯 1.2.技术对比 2.快速入门2.1.安装RabbitMQ2.1.1.单机部署(1).下载镜像方式…

SICP解读指南:深度阅读 “计算机领域三巨头” 之一(文末送书)

&#x1f308;个人主页&#xff1a;聆风吟_ &#x1f525;系列专栏&#xff1a;Linux实践室、网络奇遇记 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. 书籍介绍1.1 SICP侧重点1.2 SICP章节介绍 二. 书籍推荐2.1 书籍介绍2.2 推…

[HackMyVM]靶场 Wild

kali:192.168.56.104 主机发现 arp-scan -l # arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:d2:e0:49, IPv4: 192.168.56.104 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.56.1 0a:00:27:00:00:05 …

从安卓转战月薪6万的鸿蒙原来这么简单

近年来&#xff0c;各家大厂正在积极布局鸿蒙客户端开发&#xff0c;鸿蒙操作系统备受瞩目&#xff0c;不少安卓开发者纷纷转战鸿蒙&#xff0c;并取得了可观的经济回报。本文将为大家揭示&#xff0c;从安卓转战鸿蒙并获得月薪6万的简单之道&#xff0c;希望能给正在考虑转型的…

YOLOSHOW - YOLOv5 / YOLOv7 / YOLOv8 / YOLOv9 基于 Pyside6 的图形化界面

YOLOSHOW 是一个基于 PySide6&#xff08;Qt for Python&#xff09;开发的图形化界面应用程序&#xff0c;主要用于集成和可视化YOLO系列&#xff08;包括但不限于YOLOv5、YOLOv7、YOLOv8、YOLOv9&#xff09;的目标检测模型。YOLOSHOW 提供了一个用户友好的交互界面&#xff…

POS 之 最终确定性

Gasper Casper 是一种能将特定区块更新为 最终确定 状态的机制&#xff0c;使网络的新加入者确信他们正在同步规范链。当区块链出现多个分叉时&#xff0c;分叉选择算法使用累计投票来确保节点可以轻松选择正确的分叉。 最终确定性 最终确定性是某些区块的属性&#xff0c;意味…

Ajax、Axios、Vue、Element与其案例

目录 一.Ajax 二.Axios 三.Vue 四.Element 五.增删改查案例 一.依赖&#xff1a;数据库&#xff0c;mybatis&#xff0c;servlet&#xff0c;json-对象转换器 二.资源&#xff1a;elementvueaxios 三.pojo 四.mapper.xml与mapper接口 五.service 六.servlet 七.html页…

1909_Arm Cortex-M3编程模型

1909_Arm Cortex-M3编程模型 全部学习汇总&#xff1a; g_arm_cores: ARM内核的学习笔记 (gitee.com) 编程模型的部分除了单独的核心寄存器描述之外&#xff0c;它还包含有关处理器模式和软件执行和堆栈的特权级别的信息。 处理器有两种模式&#xff0c;分别是线程模式和Handle…

揭秘CPU可视化:探索计算机心脏的神秘之旅

在数字化飞速发展的今天&#xff0c;中央处理器&#xff08;CPU&#xff09;作为计算机的心脏&#xff0c;其复杂度和重要性不言而喻。 中央处理器&#xff0c;这个小小的芯片&#xff0c;却承载着计算机运行的所有指令和数据处理任务。它的内部构造复杂而精密&#xff0c;每一…

哪些公司在招聘GIS开发?为什么?

之前我们给大家整理汇总了WebGIS在招岗位的一些特点&#xff0c;包括行业、学历、工作经验等。WebGIS招聘原来看重这个&#xff01;整理了1300多份岗位得出来的干货&#xff01; 很多同学好奇&#xff0c;这些招GIS开发的都是哪些公司&#xff1f;主要是做什么的&#xff1f; …

Cesium 自定义Primitive - 圆

一、创作思路 1、创建一个自定义CustomPrimitive 2、然后根据两个点&#xff0c;生成圆 3、方便后期绘制圆 二、实现代码 1、在vue的包中加入turf. npm install turf/turf 1、创建一个CustomCirclePrimitive类,并加入更新的代码 export default class CustomCirclePrimitive …

【Simulink系列】——控制系统仿真基础

声明&#xff1a;本系列博客参考有关专业书籍&#xff0c;截图均为自己实操&#xff0c;仅供交流学习&#xff01; 一、控制系统基本概念 这里就不再介绍类似于开环系统、闭环系统等基本概念了&#xff01; 1、数学模型 控制系统的数学模型是指动态数学模型&#xff0c;大致…

车辆伤害VR安全教育培训复用性强

VR工地伤害虚拟体验是一种新兴的培训方式&#xff0c;它利用虚拟现实技术为参与者提供身临其境的体验。与传统的培训方式相比&#xff0c;VR工地伤害虚拟体验具有许多优势。 首先&#xff0c;VR工地伤害虚拟体验能够模拟真实的工作环境和事故场景&#xff0c;让参与者在安全的环…

基于单片机的晾衣架控制系统设计

目 录 摘 要 I Abstract II 引 言 1 1 系统方案设计 3 1.1 系统方案论证 3 1.2 系统工作原理 4 2 硬件设计 5 2.1 单片机 5 2.2 按键设计 7 2.3 光线检测模块 8 2.4 雨滴检测模块 9 2.5 电压比较器 10 2.6 微动步进电动机 11 2.7 硬件电路原理图 12 3 系统主要软件设计 14 3.1…