蓝桥杯刷题_day8_动态规划_简单多状态

2024-03-30 22:20

本文主要是介绍蓝桥杯刷题_day8_动态规划_简单多状态,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 按摩师
    • 打家劫舍
    • 打家劫舍II
    • 删除并获得点数
    • 粉刷房子

按摩师

【题目描述】
一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。给定一个预约请求序列,替按摩师找到最优的预约集合(总预约时间最长),返回总的分钟数。

【输入样例】

[1,2,3,1]

【输出样例】

4

【数据规模与约定】

【解题思路】

  • 定义两个状态数组f和g, f[i]表示前i个预约中,选择第i个预约的最大收益,g[i]表示前i个预约中,不选择第i个预约的最大收益。
  • 状态转移方程为:f[i] = g[i-1] + nums[i], g[i] = max(f[i-1], g[i-1]).
  • 最终答案为max(f[n-1], g[n-1]).

【C++程序代码】

class Solution {
public:int massage(vector<int>& nums) {int n = nums.size();if (n == 0){return 0;}vector<int> f(n);vector<int> g(n);f[0] = nums[0];g[0] = 0;for (int i = 1; i < n; i++){f[i] = g[i - 1] + nums[i];g[i] = max(f[i - 1],g[i - 1]);}return max(f[n - 1], g[n - 1]);}
};

打家劫舍

【题目描述】
一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响小偷偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警
给定一个代表每个房屋存放金额的非负整数数组 nums ,请计算 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

【输入样例】

nums = [1,2,3,1]

【输出样例】

4

【数据规模与约定】

  • 1 <= nums.length <= 100
  • 0 <= nums[i] <= 400

【解题思路】

  • 定义两个状态数组f和g, f[i]表示前i个房间中,选择偷窃第i个房间的最大收益,g[i]表示前i个房间中,不选择偷窃第i个房间的最大收益。
  • 状态转移方程为:f[i] = g[i-1] + nums[i], g[i] = max(f[i-1], g[i-1]).
  • 最终答案为max(f[n-1], g[n-1]).

【C++程序代码】

class Solution {
public:int rob(vector<int>& nums) {int n = nums.size();if (n == 0){return 0;}vector<int> f(n);vector<int> g(n);f[0] = nums[0];g[0] = 0;for (int i = 1; i < n; i++){f[i] = g[i - 1] + nums[i];g[i] = max(f[i - 1],g[i - 1]);}return max(f[n - 1], g[n - 1]);}
};

打家劫舍II

【题目描述】
一个专业的小偷,计划偷窃一个环形街道上沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警
给定一个代表每个房屋存放金额的非负整数数组 nums ,请计算 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。

【输入样例】

nums = [2,3,2]

【输出样例】

3

【数据规模与约定】

  • 1 <= nums.length <= 100
  • 0 <= nums[i] <= 1000

【解题思路】

  • 由于这个问题是一个环形的房屋,所以需要分两种情况讨论:
    1. 偷窃第一个房子,不偷窃最后一个房子
    2. 不偷窃第一个房子,偷窃最后一个房子
  • 定义一个helper函数,用来解决第一种情况(仅仅偷窃中间的房子)。
  • 最终答案为这两种情况的最大值。

【C++程序代码】

class Solution {
public:int rob(vector<int>& nums) {int n = nums.size();return max(nums[0] + rob1(nums, 2, n - 2), rob1(nums, 1, n - 1));}int rob1(vector<int>& nums, int left, int right){if (left > right){return 0;}int n = nums.size();vector<int> f(n);vector<int> g(n);f[left] = nums[left];g[0] = 0;for (int i = left + 1; i <= right; i++){f[i] = g[i - 1] + nums[i];g[i] = max(f[i - 1], g[i - 1]);}return max(f[right], g[right]);}
};

删除并获得点数

【题目描述】
给你一个整数数组 nums ,你可以对它进行一些操作。
每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除 所有 等于 nums[i] - 1nums[i] + 1 的元素。
开始你拥有 0 个点数。返回你能通过这些操作获得的最大点数。

【输入样例】

nums = [3,4,2]

【输出样例】

6

【数据规模与约定】

  • 1 <= nums.length <= 2 * 104
  • 1 <= nums[i] <= 104

【解题思路】

  • 由于每次删除一个数字,都需要删除该数字前后的数字,因此可以直接创建一个新数组arr,其中arr[i]表示数字i出现的次数乘以i
  • 然后对arr数组做一次"打家劫舍"问题的求解,得到最终结果。

【C++程序代码】

class Solution {
public:int deleteAndEarn(vector<int>& nums) {//根据题目要求直接创建一个可以包含所有可能的数组int n = nums.size();int max_nums = 0;for (int i = 0; i < n; i++){if (nums[i] > max_nums){max_nums = nums[i];}}vector<int> arr(max_nums+1);//将nums数组中的所有的数都映射到新开辟的数组中for (int i = 0; i < n; i++){arr[nums[i]] = arr[nums[i]] + nums[i];}//在arr数组中做一次“打家劫舍”问题vector<int> f(max_nums + 1);vector<int> g(max_nums + 1);f[0] = arr[0];g[0] = 0;for (int i = 1; i < max_nums + 1; i++){f[i] = g[i - 1] + arr[i];g[i] = max(f[i - 1], g[i - 1]);}return max(f[max_nums], g[max_nums]);}
};

粉刷房子

【题目描述】
假如有一排房子,共 n 个,每个房子可以被粉刷成红色、蓝色或者绿色这三种颜色中的一种,你需要粉刷所有的房子并且使其相邻的两个房子颜色不能相同。

当然,因为市场上不同颜色油漆的价格不同,所以房子粉刷成不同颜色的花费成本也是不同的。每个房子粉刷成不同颜色的花费是以一个 n x 3 的正整数矩阵 costs 来表示的。

例如,costs[0][0] 表示第 0 号房子粉刷成红色的成本花费;costs[1][2] 表示第 1 号房子粉刷成绿色的花费,以此类推。

请计算出粉刷完所有房子最少的花费成本。

【输入样例】

costs = [[17,2,17],[16,16,5],[14,3,19]]

【输出样例】

10

【数据规模与约定】

  • costs.length == n
  • costs[i].length == 3
  • 1 <= n <= 100
  • 1 <= costs[i][j] <= 20

【解题思路】

  • 定义三个状态数组rgb,分别表示当前房子刷成红色、绿色和蓝色的最小花费。
  • 状态转移方程为:
    • r[i] = min(g[i-1], b[i-1]) + costs[i-1][0];
    • g[i] = min(r[i-1], b[i-1]) + costs[i-1][1];
    • b[i] = min(r[i-1], g[i-1]) + costs[i-1][2];
  • 最终答案为min(r[n], g[n], b[n])

【C++程序代码】

class Solution {
public:int minCost(vector<vector<int>>& costs) {int n = costs.size();vector<int> r(n + 1); //红色vector<int> g(n + 1); //绿色vector<int> b(n + 1); //蓝色for (int i = 1; i <= n; i++){r[i] = min(g[i - 1], b[i - 1]) + costs[i - 1][0];g[i] = min(r[i - 1], b[i - 1]) + costs[i - 1][1];b[i] = min(r[i - 1], g[i - 1]) + costs[i - 1][2];}return min({ r[n], g[n], b[n] });}
};
class Solution {
public:int minCost(vector<vector<int>>& costs) {int n = costs.size();vector<vector<int> > dp(n + 1, vector<int>(3));for (int i = 1; i <= n; i++){dp[i][0] = min(dp[i - 1][1], dp[i - 1][2]) + costs[i - 1][0];dp[i][1] = min(dp[i - 1][0], dp[i - 1][2]) + costs[i - 1][1];dp[i][2] = min(dp[i - 1][0], dp[i - 1][1]) + costs[i - 1][2];}return min({ dp[n][0], dp[n][1], dp[n][2] });}
};

这篇关于蓝桥杯刷题_day8_动态规划_简单多状态的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/862738

相关文章

利用Python编写一个简单的聊天机器人

《利用Python编写一个简单的聊天机器人》这篇文章主要为大家详细介绍了如何利用Python编写一个简单的聊天机器人,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 使用 python 编写一个简单的聊天机器人可以从最基础的逻辑开始,然后逐步加入更复杂的功能。这里我们将先实现一个简单的

VUE动态绑定class类的三种常用方式及适用场景详解

《VUE动态绑定class类的三种常用方式及适用场景详解》文章介绍了在实际开发中动态绑定class的三种常见情况及其解决方案,包括根据不同的返回值渲染不同的class样式、给模块添加基础样式以及根据设... 目录前言1.动态选择class样式(对象添加:情景一)2.动态添加一个class样式(字符串添加:情

使用IntelliJ IDEA创建简单的Java Web项目完整步骤

《使用IntelliJIDEA创建简单的JavaWeb项目完整步骤》:本文主要介绍如何使用IntelliJIDEA创建一个简单的JavaWeb项目,实现登录、注册和查看用户列表功能,使用Se... 目录前置准备项目功能实现步骤1. 创建项目2. 配置 Tomcat3. 项目文件结构4. 创建数据库和表5.

使用PyQt5编写一个简单的取色器

《使用PyQt5编写一个简单的取色器》:本文主要介绍PyQt5搭建的一个取色器,一共写了两款应用,一款使用快捷键捕获鼠标附近图像的RGB和16进制颜色编码,一款跟随鼠标刷新图像的RGB和16... 目录取色器1取色器2PyQt5搭建的一个取色器,一共写了两款应用,一款使用快捷键捕获鼠标附近图像的RGB和16

四种简单方法 轻松进入电脑主板 BIOS 或 UEFI 固件设置

《四种简单方法轻松进入电脑主板BIOS或UEFI固件设置》设置BIOS/UEFI是计算机维护和管理中的一项重要任务,它允许用户配置计算机的启动选项、硬件设置和其他关键参数,该怎么进入呢?下面... 随着计算机技术的发展,大多数主流 PC 和笔记本已经从传统 BIOS 转向了 UEFI 固件。很多时候,我们也

SpringCloud配置动态更新原理解析

《SpringCloud配置动态更新原理解析》在微服务架构的浩瀚星海中,服务配置的动态更新如同魔法一般,能够让应用在不重启的情况下,实时响应配置的变更,SpringCloud作为微服务架构中的佼佼者,... 目录一、SpringBoot、Cloud配置的读取二、SpringCloud配置动态刷新三、更新@R

基于Qt开发一个简单的OFD阅读器

《基于Qt开发一个简单的OFD阅读器》这篇文章主要为大家详细介绍了如何使用Qt框架开发一个功能强大且性能优异的OFD阅读器,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 目录摘要引言一、OFD文件格式解析二、文档结构解析三、页面渲染四、用户交互五、性能优化六、示例代码七、未来发展方向八、结论摘要

如何用Python绘制简易动态圣诞树

《如何用Python绘制简易动态圣诞树》这篇文章主要给大家介绍了关于如何用Python绘制简易动态圣诞树,文中讲解了如何通过编写代码来实现特定的效果,包括代码的编写技巧和效果的展示,需要的朋友可以参考... 目录代码:效果:总结 代码:import randomimport timefrom math

MyBatis框架实现一个简单的数据查询操作

《MyBatis框架实现一个简单的数据查询操作》本文介绍了MyBatis框架下进行数据查询操作的详细步骤,括创建实体类、编写SQL标签、配置Mapper、开启驼峰命名映射以及执行SQL语句等,感兴趣的... 基于在前面几章我们已经学习了对MyBATis进行环境配置,并利用SqlSessionFactory核

Java中JSON字符串反序列化(动态泛型)

《Java中JSON字符串反序列化(动态泛型)》文章讨论了在定时任务中使用反射调用目标对象时处理动态参数的问题,通过将方法参数存储为JSON字符串并进行反序列化,可以实现动态调用,然而,这种方式容易导... 需求:定时任务扫描,反射调用目标对象,但是,方法的传参不是固定的。方案一:将方法参数存成jsON字