[Algorithm][动态规划][简单多状态DP问题][按摩师][打家劫舍Ⅱ][删除并获得点数][粉刷房子]详细讲解

news2024/11/14 19:48:16

目录

  • 1.按摩师
    • 1.题目链接
    • 2.算法思路详解
    • 3.代码实现
  • 2.打家劫舍 II
    • 1.题目链接
    • 2.算法思路详解
    • 3.代码实现
  • 3.删除并获得点数
    • 1.题目链接
    • 2.算法思路详解
    • 3.代码实现
  • 4.粉刷房子
    • 1.题目链接
    • 2.算法思路详解
    • 3.代码实现


1.按摩师

1.题目链接

  • 按摩师

2.算法思路详解

  • 思路
    • 确定状态表示 -> dp[i]的含义

      • 选择到i位置的时候,此时的最长预约时长
      • 本题,状态表示还可以继续细分:
        • f[i]:选择到i位置的时候,nums[i]必选,此时的最长预约时长
        • g[i]:选择到i位置的时候,nums[i]不选,此时的最长预约时长
    • 推导状态转移方程

      • f[i] = g[i - 1] + nums[i]
      • g[i] = max(f[i - 1], g[i - 1])
        请添加图片描述
    • 初始化:f[0] = nums[0], g[0] = 0

    • 确定填表顺序:从左往右,两个表一起填

    • 确定返回值:max(f[n - 1], g[n - 1])


3.代码实现

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];

    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]);
}

2.打家劫舍 II

1.题目链接

  • 打家劫舍 II

2.算法思路详解

  • 思路解析:本题比打家劫舍Ⅰ只多了环形问题,那么只需将环形问题分类讨论(依据nums[0]),拆解为两个线性的打家劫舍Ⅰ问题即可
    • 第一个位置偷nums[0] + _rob[2, n - 2] <— 第二个位置和最后一个位置不偷
    • 第一个位置不偷_rob(1, n - 1) <— 偷第二个位置和最后一个位置
  • 思路
    • 确定状态表示 -> dp[i]的含义

      • i位置的时候,此时的最大金额
      • 本题,状态表示还可以继续细分:
        • f[i]:偷到i位置的时候,nums[i]必偷,此时的最大金额
        • g[i]:偷到i位置的时候,nums[i]不偷,此时的最大金额
    • 推导状态转移方程

      • f[i] = g[i - 1] + nums[i]
      • g[i] = max(f[i - 1], g[i - 1])
        请添加图片描述
    • 初始化:f[0] = nums[0], g[0] = 0

    • 确定填表顺序:从左往右,两个表一起填

    • 确定返回值:max(f[n - 1], g[n - 1])


3.代码实现

class Solution
{
public:
    int rob(vector<int>& nums) 
    {
        int n = nums.size();
        
        // 分类讨论,取两种情况中的最大值
        return max(nums[0] + _rob(nums, 2, n - 2), _rob(nums, 1, n - 1));
    }
    
    int _rob(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];
        
        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]);
    }
};

3.删除并获得点数

1.题目链接

  • 删除并获得点数

2.算法思路详解

  • 思路解析:本题可以先做一个预处理,将问题转化为打家劫舍

    • 思路
      • 打家劫舍要求访问数组中的数的顺序是连续的,但本题原始数组显然不符合要求
      • 虽然原始数组数值不符合要求,但是经过转换,数组下标是可以符合顺序连续的
    • 做法
      • 将原始数组中的数,统计到arr,然后在arr中,做一次打家劫舍问题即可
      • 此时,数值相同的值的和可以被其本身值作为arr的下标索引到 <— hash[x] = sum(x)
      • arr[i]i这个数出现的总和
        请添加图片描述
  • 思路

    • 确定状态表示 -> dp[i]的含义

      • i位置的时候,此时获得的最大点数
      • 本题,状态表示还可以继续细分:
        • f[i]:选到i位置的时候,nums[i]必选,此时获得的最大点数
        • g[i]:选到i位置的时候,nums[i]不选,此时获得的最大点数
    • 推导状态转移方程

      • f[i] = g[i - 1] + arr[i]
      • g[i] = max(f[i - 1], g[i - 1])
        请添加图片描述
    • 初始化:f[0] = arr[0], g[0] = 0

    • 确定填表顺序:从左往右,两个表一起填

    • 确定返回值:max(f[n], g[n])


3.代码实现

int deleteAndEarn(vector<int>& nums) 
{
    sort(nums.begin(), nums.end());
    int n = nums.back(); // max

    vector<int> arr(n + 1);
    for(auto& x : nums)
    {
        arr[x] += x;
    }

    vector<int> f(n + 1);
    vector<int> g(n + 1);
    for(int i = 1; i <= n; i++)
    {
        f[i] = g[i - 1] + arr[i];
        g[i] = max(f[i - 1], g[i - 1]);
    }

    return max(f[n], g[n]);
}

4.粉刷房子

1.题目链接

  • 粉刷房子

2.算法思路详解

  • 思路
    • 确定状态表示 -> dp[i][j]的含义:i -> 到了哪个位置,j -> 这个位置的哪个颜色

      • dp[i][0]:粉刷i位置的时候,最后一个位置刷上红色,此时的最小花费
      • dp[i][1]:粉刷i位置的时候,最后一个位置刷上蓝色,此时的最小花费
      • dp[i][2]:粉刷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]
        请添加图片描述
    • 初始化:dp[0][0] = dp[0][1] = dp[0][2] = 0

    • 确定填表顺序:从左往右,一次填写三个表

    • 确定返回值:min(dp[n][0], min(dp[n][1], dp[n][2]))


3.代码实现

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], min(dp[n][1], dp[n][2]));
}

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

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

相关文章

《计算机网络微课堂》3-10 以太网交换机的生成树协议 STP

我们介绍以太网交换机生成树协议的基本概念。 请大家思考一下&#xff0c;应该如何提高以太网的可靠性呢&#xff1f;例如如图所示的以太网&#xff0c;由三台交换机互联而成&#xff0c;每个交换机上都连接有一些主机&#xff0c;为了简单起见&#xff0c;我们只画出了每个交…

源码部署ELK

目录 资源列表 基础环境 关闭防护墙 关闭内核安全机制 修改主机名 添加hosts映射 一、部署elasticsearch 修改limit限制 部署elasticsearch 修改配置文件 单节点 集群(3台节点集群为例) 启动 二、部署logstash 部署logstash 添加配置文件 启动 三、部署kiban…

嵌入式全栈开发学习笔记---C语言笔试复习大全22

目录 结构体 结构体的声明 定义结构体变量 访问结构体成员进行初始化 通过结构体变量名访问结构体成员 结构体指针 结构体指针的定义 通过结构体指针访问结构体成员 结构体数组 结构体数组的定义 遍历结构体数组 结构体的长度&#xff08;笔试重点&#xff09; 上一…

在家庭影院音频中应用的D类音频放大器

家庭影院的主要组成部分包括显示设备、音响设备、信号源和接线设备等。家庭影院的音响信号需要进行处理和输出&#xff0c;以获得高质量的音效。音响设备通常需要一台功率适当的数字、模拟混合的处理器&#xff0c;对音源进行降噪、均衡、扩展等处理操作&#xff0c;以达到高品…

VMare下载安装

一.下载 1.百度搜索BROADCOM官网 打开官网&#xff1a; https://www.broadcom.com/​ 2.点击右上角&#xff0c;进行账号注册&#xff0c;注册好后&#xff0c;进行登陆 3.注册好后&#xff0c;进入个人界面&#xff1a;https://support.broadcom.com/#. 按下图所示点击进…

React 组件创建以及使用

1.创建和嵌套组件 React 应用程序是由 组件 组成的。一个组件是 UI&#xff08;用户界面&#xff09;的一部分&#xff0c;它拥有自己的逻辑和外观。组件可以小到一个按钮&#xff0c;也可以大到整个页面。 React 组件是返回标签的 JavaScript 函数&#xff1a; function My…

【计算机毕业设计】基于SSM+Vue的校园美食交流系统【源码+lw+部署文档】

目录 前 言 第1章 概述 1.1 研究背景 1.2 研究目的 1.3 研究内容 第二章 开发技术介绍 2.1 Java技术 2.2 Mysql数据库 2.3 B/S结构 2.4 SSM框架 第三章 系统分析 3.1 可行性分析 3.1.1 技术可行性 3.1.2 经济可行性 3.1.3 操作可行性 3.2 系统性能分析 3.3 系…

无线技术整合到主动噪声控制(ANC)增强噪声降低性能

主动噪声控制&#xff08;ANC&#xff09;已成为一种广泛使用的降噪技术。基本原理是通过产生与外界噪音相等的反向声波&#xff0c;将噪音中和&#xff0c;从而达到降噪的效果。ANC系统通常包括以下几个部分&#xff1a;参考麦克风、处理芯片、扬声器和误差麦克风。参考麦克风…

Drone+Gitee自动执行构建、测试和发布工作流

拉取Drone:(至于版本&#xff0c;你可以下载最新的) sudo docker pull drone/drone:2 拉取runner&#xff1a; sudo docker pull drone/drone-runner-docker 在Gitee中添加第三方应用&#xff1a; 进入个人主页&#xff0c;点击设置&#xff1a; 往下翻&#xff0c;找到数…

Web工程和Servlet

使用idea创建web项目 第一种方式&#xff1a;使用原型创建web项目&#xff0c; Archetype的选择如下图&#xff1a; 创建完成&#xff1a; 第二种方式&#xff1a;不使用原型创建web工程 点击new,选择tomcat的bin的上一级目录 创建完毕 使用&#xff1a; 再webapp目录下…

重新思考:Netflix 的边缘负载均衡

声明 本文是对Netflix 博客的翻译 前言 ​ 在先前关于Zuul 2开源的文章中&#xff0c;我们简要概述了近期在负载均衡方面的一些工作。在这篇文章中&#xff0c;我们将更详细地介绍这项工作的原因、方法和结果。 ​ 因此&#xff0c;我们开始从Zuul和其他团队那里学习&#…

【限免】杂波环境下线性调频脉冲、巴克码、频率步进脉冲雷达MTI、脉冲压缩【附MATLAB代码】

来源&#xff1a;微信公众号&#xff1a;EW Frontier 本代码主要模拟杂波环境&#xff08;飞机、地杂波、鸟类信号&#xff09;下&#xff0c;Chirp脉冲、巴克码脉冲、频率步进脉冲雷达信号的脉冲压缩及MTI、​匹配滤波。 MATLAB主代码 % 定义参数 fs 1000; % 采样率 T 1; …

C语言 | Leetcode C语言题解之第106题从中序与后序遍历序列构造二叉树

题目&#xff1a; 题解&#xff1a; int post_idx;typedef struct {int key;int val;UT_hash_handle hh; } hashTable;hashTable* idx_map;void insertHashTable(int x, int y) {hashTable* rec malloc(sizeof(hashTable));rec->key x;rec->val y;HASH_ADD_INT(idx_m…

九、图形化脚本

多年来&#xff0c; shell脚本一直都被认为是枯燥乏味的。但如果你准备在图形化环境中运行脚本时&#xff0c;就未必如此了。有很多与脚本用户交互的方式并不依赖read和echo语句。 9.1 创建文本菜单 创建交互式shell脚本最常用的方法是使用菜单。提供各种选项可以帮助脚本用户…

牛客NC295 连续子链表最大和【simple 动态规划 Java/Go/PHP/C++】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/650b68dfa69d492d92645aecd7da9b21 思路 动态规划动态规划算法通过迭代遍历输入数组&#xff0c;维护一个额外的数组 dp 来记录截止到每个位置的最大连续子数组和&#xff0c;并利用一个变量 max_num 实时更新全…

面向可复用性和可维护性的设计模式 课程学习总结

什么是设计模式 设计模式&#xff1a;在软件设计中给定上下文中常见问题的通用的、可重用的解决方案。 设计模式分类 1. 创建型模式——Creational patterns 关注对象创建的过程 1.1 工厂方法模式 定义用于创建对象的接口&#xff0c;但让子类决定要实例化哪个类。工厂方…

swift中json和字典Dict或者数组相互转换,JSONSerialization的强大使用

在Swift中&#xff0c;你可以使用JSONSerialization类将JSON字符串转换为字典。要将 Swift 字典转换为 JSON 字符串&#xff0c;我们可以使用JSONSerialization类的data(withJSONObject:options:)方法。这个方法将字典转换为二进制数据&#xff0c;然后我们可以使用String(data…

Leetcode 环形链表|| 快慢指针解法

但是我们不知道 aaa 的值&#xff0c;该怎么办&#xff1f;依然是使用双指针法。考虑构建一个指针&#xff0c;此指针需要有以下性质&#xff1a;此指针和 slow 一起向前走 a 步后&#xff0c;两者在入口节点重合。那么从哪里走到入口节点需要 aaa 步&#xff1f;答案是链表头节…

SAP-CO成本控制概念之标准成本

“ 本篇介绍&#xff1a;标准成本的会计概念&#xff0c;标准成本的制定标准&#xff1b;通过结合会计标准成本的概念与SAP CO标准成本估算功能&#xff0c;更具象化的了解SAP如何实现标准成本管理&#xff0c;为后续学习SAP实际成本核算打下基础。” 01 — 背景需求 SAP实施…

【C++】深入解析C++智能指针:从auto_ptr到unique_ptr与shared_ptr

文章目录 前言&#xff1a;1. 智能指针的使用及原理2. C 98 标准库中的 auto_ptr:3. C 11 中的智能指针循环引用&#xff1a;shared_ptr 定制删除器 4. 内存泄漏总结&#xff1a; 前言&#xff1a; 随着C语言的发展&#xff0c;智能指针作为现代C编程中管理动态分配内存的一种…