蓝桥杯练习题——dp
五部曲(代码随想录)
1.确定 dp 数组以及下标含义
2.确定递推公式
3.确定 dp 数组初始化
4.确定遍历顺序
5.debug
入门题
1.斐波那契数

思路
1.f[i]:第 i 个数的值
2.f[i] = f[i - 1] + f[i - 2]
3.f[0] = 0, f[1] = 1
4.顺序遍历
5.记得特判 n == 0 的时候,因为初始化了 f[1]
class Solution {
public:int fib(int n) {if(n == 0) return n;vector<int> f(n + 1);f[0] = 0, f[1] = 1;for(int i = 2; i <= n; i++) f[i] = f[i - 1] + f[i - 2];return f[n];}
};
2.爬楼梯

思路
每次可以从下面一个台阶或者下面两个台阶处上来
1.f[i]:爬到第 i 阶楼梯有多少种方法
2.f[i] = f[i - 1] + f[i - 2]
3.f[0] = 1, f[1] = 1
4.顺序遍历
class Solution {
public:int climbStairs(int n) {vector<int> f(n + 1);f[0] = 1, f[1] = 1;for(int i = 2; i <= n; i++) f[i] = f[i - 1] + f[i - 2];return f[n];}
};
3.使用最小花费爬楼梯

思路
可以从 0 或 1 处开始爬楼梯,需要爬到第 n 阶楼梯
1.f[i]:爬到第 i 阶楼梯需要的最小花费
2.f[i] = min(f[i - 1] + cost[i - 1], f[i - 2] + cost[i - 2)
3.f[0] = 0, f[1] = 0
4.顺序遍历
class Solution {
public:int minCostClimbingStairs(vector<int>& cost) {int n = cost.size();vector<int> f(n + 1);f[0] = 0, f[1] = 0;for(int i = 2; i <= n; i++){f[i] = min(f[i - 1] + cost[i - 1], f[i - 2] + cost[i - 2]);}return f[n];}
};
4.不同路径

思路
1.f[i][j]: 走到 (i, j) 总共的路径
2.f[i][j] = f[i - 1][j] + f[i][j - 1]
3.f[i][1] = 1, f[1][i] = 1
4.顺序遍历
class Solution {
public:int uniquePaths(int m, int n) {vector<vector<int>> f(n + 1, vector<int>(m + 1));for(int i = 0; i <= n; i++) f[i][1] = 1;for(int i = 0; i <= m; i++) f[1][i] = 1;for(int i = 2; i <= n; i++){for(int j = 2; j <= m; j++){f[i][j] = f[i - 1][j] + f[i][j - 1];}}return f[n][m];}
};
5.不同路径 II

思路
1.f[i][j]: 走到 (i, j) 总共的路径
2.f[i][j] = f[i - 1][j] + f[i][j - 1]
3.f[i][0] = 1, f[0][i] = 1, 其他 = 0
4.顺序遍历
class Solution {
public:int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {int n = obstacleGrid.size();int m = obstacleGrid[0].size();vector<vector<int>> f(n, vector<int>(m, 0));for(int i = 0; i < n && !obstacleGrid[i][0]; i++) f[i][0] = 1;for(int i = 0; i < m && !obstacleGrid[0][i]; i++) f[0][i] = 1;for(int i = 1; i < n; i++){for(int j = 1; j < m; j++){if(!obstacleGrid[i][j]){f[i][j] = f[i - 1][j] + f[i][j - 1];}}}return f[n - 1][m - 1];}
};
6.整数拆分

思路
1.f[i]: 拆数字 i 可得到的最大乘积
2.拆分成 j * (i - j) 或 j * f[i - j],f[i] = max(f[i], max(j * (i - j), j * [i - j]))
3.f[0] = 0, f[1] = 1
4.顺序遍历
class Solution {
public:int integerBreak(int n) {vector<int> f(n + 1);f[0] = 0, f[1] = 1;for(int i = 2; i <= n; i++){for(int j = 0; j < i; j++){f[i] = max(f[i], max(j * (i - j), j * f[i - j]));}}return f[n];}
};
7.不同的二叉搜索树

思路
dp[3],就是 元素1为头结点搜索树的数量 + 元素2为头结点搜索树的数量 + 元素3为头结点搜索树的数量
元素1为头结点搜索树的数量 = 右子树有2个元素的搜索树数量 * 左子树有0个元素的搜索树数量
元素2为头结点搜索树的数量 = 右子树有1个元素的搜索树数量 * 左子树有1个元素的搜索树数量
元素3为头结点搜索树的数量 = 右子树有0个元素的搜索树数量 * 左子树有2个元素的搜索树数量
有2个元素的搜索树数量就是dp[2]。
有1个元素的搜索树数量就是dp[1]。
有0个元素的搜索树数量就是dp[0]。
所以dp[3] = dp[2] * dp[0] + dp[1] * dp[1] + dp[0] * dp[2]
dp[i] += dp[以j为头结点左子树节点数量] * dp[以j为头结点右子树节点数量]
1.f[i]: 由 1 到 i 个节点的二叉搜索树个数
2.f[i] += f[j - 1] * f[i - j]
3.f[0] = 1
4.顺序遍历
class Solution {
public:int numTrees(int n) {vector<int> f(n + 1);f[0] = 1;for(int i = 1; i <= n; i++){for(int j = 1; j <= i; j++){f[i] += f[j - 1] * f[i - j];}}return f[n];}
};
背包问题
1.01背包问题

思路
1.f[i][j]: 前 i 个物品在容量为 j 的情况下的最大价值
2.f[i][j] = max(f[i - 1][j], f[i - 1][j - v[i]] + w[i])
3.全部 = 0
4.顺序遍历
#include<iostream>
using namespace std;
const int N = 1e3 + 10;
int f[N][N], v[N], w[N];
int n, m;int main(){scanf("%d%d", &n, &m);for(int i = 1; i <= n; i++) scanf("%d%d", &v[i], &w[i]);for(int i = 1; i <= n; i++){for(int j = 0; j <= m; j++){// 不选f[i][j] = f[i - 1][j];// 选if(v[i] <= j) f[i][j] = max(f[i - 1][j], f[i - 1][j - v[i]] + w[i]);}}printf("%d", f[n][m]);return 0;
}// 滚动数组优化
#include<iostream>
using namespace std;
const int N = 1e3 + 10;
int f[N], v[N], w[N];
int n, m;int main(){scanf("%d%d", &n, &m);for(int i = 1; i <= n; i++) scanf("%d%d", &v[i], &w[i]);for(int i = 1; i <= n; i++){for(int j = m; j >= v[i]; j--){f[j] = max(f[j], f[j - v[i]] + w[i]);}}printf("%d", f[m]);return 0;
}
2.分割等和子集

思路
分割成两个等和子集,即找到是否存在和为 sum / 2 的子集,转化为 01 背包,背包容量为 sum / 2
1.f[j]: 背包容量为 i,放入物品后的最大重量
2.f[j] = max(f[j], f[j - nums[i]] + nums[i])
3.全部 = 0
4.倒序遍历
class Solution {
public:bool canPartition(vector<int>& nums) {int n = nums.size(), sum = 0;for(int i = 0; i < n; i++) sum += nums[i];if(sum % 2) return false;vector<int> f(10001, 0);for(int i = 0; i < n; i++){for(int j = sum / 2; j >= nums[i]; j--){f[j] = max(f[j], f[j - nums[i]] + nums[i]);if(f[j] == sum / 2) return true;}}return false;}
};
3.最后一块石头的重量 II

思路
尽可能分成两堆重量相同,使得相撞后重量最小
1.f[j]: 容量为 j 的背包,最大价值
2.f[j] = max(f[j], f[j - stones[i]] + stones[i])
3.全部 = 0
4.倒序遍历
class Solution {
public:int lastStoneWeightII(vector<int>& stones) {int n = stones.size(), sum = 0;for(int i = 0; i < n; i++) sum += stones[i];vector<int> f(1501, 0);for(int i = 0; i < n; i++){for(int j = sum / 2; j >= stones[i]; j--){f[j] = max(f[j], f[j - stones[i]] + stones[i]);}}return (sum - f[sum / 2]) - f[sum / 2];}
};
4.目标和

思路
pos - neg = tar 得 pos - (sum - pos) = tar 得 pos = (sum + tar) / 2
转换为背包容量为 pos,有多少种情况装满
无解的情况:pos 为奇数,tar 的绝对值大于 sum
只要搞到 nums[i],凑成 f[j] 就有 f[j - nums[i]] 种方法。
例如:f[j],j 为5,
已经有一个1(nums[i])的话,有 f[4]种方法 凑成 容量为5的背包。
已经有一个2(nums[i])的话,有 f[3]种方法 凑成 容量为5的背包。
已经有一个3(nums[i])的话,有 f[2]中方法 凑成 容量为5的背包
已经有一个4(nums[i])的话,有 f[1]中方法 凑成 容量为5的背包
已经有一个5(nums[i])的话,有 f[0]中方法 凑成 容量为5的背包
那么凑整 f[5] 有多少方法呢,也就是把 所有的 f[j - nums[i]] 累加起来。
1.f[j]:填满 j 背包有多少种情况
2.f[j] += f[j - nums[i]]
3.f[0] = 1,其他 = 0
4.倒序遍历
class Solution {
public:int findTargetSumWays(vector<int>& nums, int target) {int n = nums.size(), sum = 0;for(int i = 0; i < n; i++) sum += nums[i];if((sum + target) % 2 || abs(target) > sum) return 0;int pos = (sum + target) / 2;vector<int> f(pos + 1, 0);f[0] = 1;for(int i = 0; i < n; i++){for(int j = pos; j >= nums[i]; j--){f[j] += f[j - nums[i]];}}return f[pos];}
};
5.一和零

思路
可以等价为两个 01 背包,一个装 0,一个装 1
1.f[i][j]: 最多有 i 个 0 和 j 个 1 的最长子集大小
2.f[i][j] = max(f[i][j], f[i - zero][j - one] + 1)
3.全部 = 0
4.倒序遍历
class Solution {
public:int findMaxForm(vector<string>& strs, int m, int n) {vector<vector<int>> f(m + 1, vector<int>(n + 1, 0));for(auto str : strs){int zero = 0, one = 0;for(int i = 0; i < str.size(); i++){if(str[i] == '0') zero++;else one++; }for(int i = m; i >= zero; i--){for(int j = n; j >= one; j--){f[i][j] = max(f[i][j], f[i - zero][j - one] + 1);}}}return f[m][n];}
};
相关文章:
蓝桥杯练习题——dp
五部曲(代码随想录) 1.确定 dp 数组以及下标含义 2.确定递推公式 3.确定 dp 数组初始化 4.确定遍历顺序 5.debug 入门题 1.斐波那契数 思路 1.f[i]:第 i 个数的值 2.f[i] f[i - 1] f[i - 2] 3.f[0] 0, f[1] 1 4.顺序遍历 5.记得特判 …...
kotlin基础语法
1.变量 var a:Int 2 //声明类型的可变变量 var b 3 //代码推测可变变量类型 val c 6 //代码推测不可变常量类型 var d:String?null //可为null的String类型的可变变量 latei…...
淘宝天猫商家爬虫工具 电商采集软件使用教程
介绍: 淘宝和天猫是中国最大的电商平台之一,商家在这里销售各种商品。在市场竞争激烈的环境下,了解竞争对手的商品信息和价格变化对于电商运营来说非常重要。本文将介绍如何使用Python编写一个简单的淘宝天猫商家爬虫工具,以获取商…...
建库建表时,最容易忽略的10个细节
大家使用 DolphinDB 创建数据库和表时,有时对于分区列、分区类型和排序列的选择并不十分清晰。如果不加注意,可能导致查询速度变慢、数据丢失或插入错误等问题。合理地设置分区列、排序列和分区类型,有助于加快查询速度,减少内存使…...
【基础知识】什么是 PPO(Proximal Policy Optimization,近端策略优化)
什么是 PPO(Proximal Policy Optimization,近端策略优化) PPO(Proximal Policy Optimization,近端策略优化)是一种强化学习算法,由John Schulman等人在2017年提出。PPO属于策略梯度方法&#x…...
程序员如何选择职业赛道?
程序员如何选择职业赛道? 程序员的职业赛道就像是一座迷宫,充满了各种各样的岔路口。每个岔路口都代表着不同的方向,不同的技术领域,不同的职业发展道路。 前端开发 前端开发就像迷宫中的美丽花园,它是用户与网站或应…...
[LeetBook]【学习日记】寻找和为指定数字的连续数字
题目 文件组合 待传输文件被切分成多个部分,按照原排列顺序,每部分文件编号均为一个 正整数(至少含有两个文件)。传输要求为:连续文件编号总和为接收方指定数字 target 的所有文件。请返回所有符合该要求的文件传输组…...
阿里云中小企业扶持权益
为企业提供云资源和技术服务,助力企业开启智能时代创业新范式。阿里云推出中小企业扶持权益 上云必备,助力企业长期低成本用云 一、ECS-经济型e实例、ECS u1实例活动规则 活动时间 2023年10月31日0点0分0秒至2026年3月31日23点59分59秒 活动对象 同时满…...
2核4g服务器能支持多少人访问?并发数性能测评
2核4g服务器能支持多少人访问?支持80人同时访问,阿腾云使用阿里云2核4G5M带宽服务器,可以支撑80个左右并发用户。阿腾云以Web网站应用为例,如果视频图片媒体文件存储到对象存储OSS上,网站接入CDN,还可以支持…...
Anthropic官宣Claude3:建立大模型 推理、数学、编码和视觉等方面 新基准
文章目录 1. product2. Main2.1 核心能力2.2 打榜表现 3. My thoughtsReference Claude 3 在推理、数学、编码、多语言理解和视觉方面,全面超越GPT-4在内的所有大模型,重新树立大模型基准。 1. product https://claude.ai/ 国内暂不能使用,…...
STM32 TIM编码器接口
单片机学习! 目录 文章目录 前言 一、编码器接口简介 1.1 编码器接口作用 1.2 编码器接口工作流程 1.3 编码器接口资源分布 1.4 编码器接口输入引脚 二、正交编码器 2.1 正交编码器功能 2.2 引脚作用 2.3 如何测量方向 2.4 正交信号优势 2.5 执行逻辑 三、编码器定时…...
Jupyter Notebook的安装和使用(windows环境)
一、jupyter notebook 安装 前提条件:安装python环境 安装python环境步骤: 1.下载官方python解释器 2.安装python 3.命令行窗口敲击命令pip install jupyter 4.安装jupyter之后,直接启动命令jupyter notebook,在默认浏览器中打开jupyte…...
Platformview在iOS与Android上的实现方式对比
Android中早期版本Platformview的实现基于Virtual Display。VirtualDisplay方案的原理是,先将Native View绘制到虚显,然后Flutter通过从虚显输出中获取纹理并将其与自己内部的widget树进行合成,最后作为Flutter在 Android 上更大的纹理输出的…...
使用lnmp环境部署laravel框架需要注意的点
1,上传项目文件后,需要chmod -R 777 storage授予文件权限,不然会报错file_put_contents(/): failed to open stream: Permission denied。 如果后面还是报错没有权限的话,就执行ps -ef |grep php查询php运行用户。然后执行chown …...
AI-RAN联盟在MWC24上正式启动
AI-RAN联盟在MWC24上正式启动。它的logo是这个样的: 2月26日,AI-RAN联盟(AI-RAN Alliance)在2024年世界移动通信大会(MWC 2024)上成立。创始成员包括亚马逊云科技、Arm、DeepSig、爱立信、微软、诺基亚、美…...
Reactor详解
目录 1、快速上手 介绍 2、响应式编程 2.1. 阻塞是对资源的浪费 2.2. 异步可以解决问题吗? 2.3.1. 可编排性与可读性 2.3.2. 就像装配流水线 2.3.3. 操作符(Operators) 2.3.4. subscribe() 之前什么都不会发生 2.3.5. 背压 2.3.6. …...
实践航拍小目标检测,基于YOLOv5全系列【n/s/m/l/x】参数模型开发构建无人机航拍场景下的小目标检测识别分析系统
关于无人机相关的场景在我们之前的博文也有一些比较早期的实践,感兴趣的话可以自行移步阅读即可: 《deepLabV3Plus实现无人机航拍目标分割识别系统》 《基于目标检测的无人机航拍场景下小目标检测实践》 《助力环保河道水质监测,基于yolov…...
分布式数据库中全局自增序列的实现
自增序列广泛使用于数据库的开发和设计中,用于生产唯一主键、日志流水号等唯一ID的场景。传统数据库中使用Sequence和自增列的方式实现自增序列的功能,在分布式数据库中兼容Oracle和MySQL等传统数据库语法,也是基于Sequence和自增列的方式实现…...
【论文阅读】TensoRF: Tensorial Radiance Fields 张量辐射场
发表于ECCV2022. 论文地址:https://arxiv.org/abs/2203.09517 源码地址:https://github.com/apchenstu/TensoRF 项目地址:https://apchenstu.github.io/TensoRF/ 摘要 本文提出了TensoRF,一种建模和重建辐射场的新方法。不同于Ne…...
深入了解 Android 中的 FrameLayout 布局
FrameLayout 是 Android 中常用的布局之一,它允许子视图堆叠在一起,可以在不同位置放置子视图。在这篇博客中,我们将详细介绍 FrameLayout 的属性及其作用。 <FrameLayout xmlns:android"http://schemas.android.com/apk/res/androi…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...
BLEU评分:机器翻译质量评估的黄金标准
BLEU评分:机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域,衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标,自2002年由IBM的Kishore Papineni等人提出以来,…...
