【动态规划】速解简单多状态类问题

news2024/12/31 4:28:48

目录

17.16 按摩师

题⽬描述:

解法(动态规划):

1. 状态表⽰:

2. 状态转移⽅程:

3. 初始化:

4. 填表顺序

5. 返回值

代码

总结:

213.打家劫舍II(medium)

 题⽬描述:

 解法(动态规划)

代码:

740.删除并获得点数

题⽬描述:

 解法(动态规划):

代码:

剑指OfferI I091. 粉刷房⼦

题⽬描述:

解题思路:

代码:


17.16 按摩师

 //打家劫舍问题的变形~⼩偷变成了按摩师

题⽬描述:

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

解法(动态规划):

算法思路:

1. 状态表⽰:

对于简单的线性dp ,我们可以⽤「经验+题⽬要求」来定义状态表⽰:

  • i. 以某个位置为结尾,巴拉巴拉;
  • ii. 以某个位置为起点,巴拉巴拉。

这⾥我们选择⽐较常⽤的⽅式,以某个位置为结尾,结合题⽬要求,定义⼀个状态表⽰:

dp[i] 表⽰:选择到 i 位置时,此时的最⻓预约时⻓。

 但是我们这个题在 i 位置的时候,会⾯临「选择」或者「不选择」两种抉择,所依赖的状态需要 细分:

▪ f[i] 表⽰:选择到 i 位置时, nums[i] 必选,此时的最⻓预约时⻓;

▪ g[i] 表⽰:选择到 i 位置时, nums[i] 不选,此时的最⻓预约时⻓。

2. 状态转移⽅程:

因为状态表⽰定义了两个,因此我们的状态转移⽅程也要分析两个:

相当于是有 选和不选两种状态

对于f[i] :

▪ 如果nums[i] 必选,那么我们仅需知道i - 1 位置在不选的情况下的最⻓预约时⻓, 然后加上nums[i] 即可,因此f[i] = g[i - 1] + nums[i] 。

对于g[i] :

 ▪ 如果nums[i] 不选,那么i - 1 位置上选或者不选都可以。因此,我们需要知道i - 1 位置上选或者不选两种情况下的最⻓时⻓,因此g[i] = max(f[i - 1], g[i - 1]) 。

3. 初始化:

这道题的初始化⽐较简单,因此⽆需加辅助节点,仅需初始化 f[0] = nums[0], g[0] = 0 即可。

4. 填表顺序

根据「状态转移⽅程」得「从左往右,两个表⼀起填」。

5. 返回值

应该返回max(f[n - 1], g[n - 1]) 。

代码

class Solution {
public:
    int massage(vector<int>& nums) {
        int n = nums.size();
        if (n == 0) {
            return 0;
        }//要记得特例情况的判断
        vector<int> f(n);
        auto g = f;
        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(g[n - 1], f[n - 1]);
    }
};

总结:

213.打家劫舍II(medium)

 题⽬描述:

你是⼀个专业的⼩偷,计划偷窃沿街的房屋,每间房内都藏有⼀定的现⾦。这个地⽅所有的房屋都围成⼀圈,这意味着第⼀个房屋和最后⼀个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防 盗系统,如果两间相邻的房屋在同⼀晚上被⼩偷闯⼊,系统会⾃动报警。给定⼀个代表每个房屋存放⾦额的⾮负整数数组,计算你在不触动警报装置的情况下,今晚能够偷 窃到的最⾼⾦额。

//理解:就是不能两个房间连着偷,就还是f or g 的问题啦

 解法(动态规划)

算法思路: 这⼀个问题是「打家劫舍I」问题的变形。

上⼀个问题是⼀个「单排」的模式,这⼀个问题是⼀个「环形」的模式,也就是⾸尾是相连的。但 是我们可以将「环形」问题转化为「两个单排」问题

a. 偷第⼀个房屋时的最⼤⾦额x ,此时不能偷最后⼀个房⼦,因此就是偷[0, n - 2] 区间 的房⼦; b. 不偷第⼀个房屋时的最⼤⾦额y ,此时可以偷最后⼀个房⼦,因此就是偷[1, n - 1] 区 间的房⼦;

两种情况下的「最⼤值」,就是最终的结果。

因此,问题就转化成求「两次单排结果的最大值」。 

代码:

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;
        // 1. 创建 dp 表
        // 2. 初始化
        // 3. 填表
        // 4. 返回结果
        int n = nums.size();
        vector<int> f(n);
        auto g = f;
        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]);
    }
};

740.删除并获得点数

题⽬描述:

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

 解法(动态规划):

算法思路: 其实这道题依旧是「打家劫舍I」问题的变型。

我们注意到题⽬描述,选择x 数字的时候, x - 1 与x + 1 是不能被选择的。像不像「打家 劫舍」问题中,选择i 位置的⾦额之后,就不能选择i - 1 位置以及i + 1 位置的⾦额呢~

因此,我们可以创建⼀个⼤⼩为10001 (根据题⽬的数据范围)的 hash 数组,将nums 数组中每⼀个元素x ,累加到hash 数组下标为x 的位置处,然后在hash 数组上来⼀次「打 家劫舍」即可。

代码:

class Solution {
public:
    int deleteAndEarn(vector<int>& nums) {
        const int N = 10001;
        // 1. 预处理
        //把没见过的往见过的上面靠
        int arr[N] = {0};
        for (auto x : nums)
            arr[x] += x;//记录重复数字的和
        // 2. 在 arr 数组上,做⼀次 “打家劫舍” 问题
        // 创建 dp 表
        vector<int> f(N);
        auto g = f;
        // 填表
        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 - 1], g[N - 1]);
    }
};

 预处理:把没见过的往见过的上面靠~

剑指OfferI I091. 粉刷房⼦

题⽬描述:

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

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

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

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

示例 1:

输入: costs = [[17,2,17],[16,16,5],[14,3,19]]
输出: 10
解释: 将 0 号房子粉刷成蓝色,1 号房子粉刷成绿色,2 号房子粉刷成蓝色
     最少花费: 2 + 5 + 3 = 10。

示例 2:

输入: costs = [[7,6,2]]
输出: 2

解题思路:

代码:

class Solution {
public:
    int minCost(vector<vector<int>>& costs){
        int minCost(vector<vector<int>> & costs){
            // dp[i][j] 第i个房⼦刷成第j种颜⾊最⼩花费
            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][1], dp[i - 1][0]) + costs[i - 1][2];
    }
    return min(dp[n][0], min(dp[n][1], dp[n][2]));//只能两个一min
}
}
;

sum:

1.情况选择的表示:

两种:f or g

三种:二维数组

2.然后分别写出情况下的dp方程

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

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

相关文章

实践部署 浦语·灵笔2 模型,写作图文并茂的文章

1 初步介绍 XComposer2 相关知识 浦语灵笔2 是基于 书生浦语2 大语言模型研发的突破性的图文多模态大模型&#xff0c;具有非凡的图文写作和图像理解能力&#xff0c;在多种应用场景表现出色&#xff0c;总结起来其具有&#xff1a; 自由指令输入的图文写作能力&#xff1a; 浦…

解读makefile中的延迟变量与即时变量

在 Makefile 中&#xff0c;有两种类型的变量&#xff1a;即时变量&#xff08;immediate variable&#xff09;和延迟变量&#xff08;deferred variable&#xff09;。 它们在 Makefile 的执行过程中具有不同的特性和行为。 即时变量&#xff08;Immediate Variable&#x…

adb 连接机顶盒命令

抓机顶盒日志的方法&#xff0c;使用此命令进行抓日志&#xff0c;个别无法抓日志的盒子可以使用此方法 1、安卓9.0版本查询命令 ps -ef |grep com.cm.webos.iptv 2、安卓4.4版本查询命令 ps |grep com.cm.webos.iptv 3、查询顺序&#xff1a;首先进入shell下进行操作 adb she…

php 连接sqlserver步骤

1.首先要确定使用的是sqlserver的哪个版本&#xff0c;比如sqlserver2012 2.确定服务器是64位还是32位的 3.确认一下使用php的哪个版本&#xff0c;比如php7.1 SQL Server 的 Microsoft PHP 驱动程序 Microsoft Drivers for PHP 支持矩阵 - PHP drivers for SQL Server | Mi…

基于遗传优化的货柜货物摆放优化问题求解matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于遗传优化的货柜货物摆放优化问题求解matlab仿真。在一个货架上&#xff0c;初始状态下&#xff0c;随机将货物放在货柜上&#xff0c;优化之后&#xff0c;整…

javaIO流知识点概况

一、前言&#xff1a; 1.1.流的概念: java将输入与输出比喻为"流"&#xff0c;英文:Stream. 就像生活中的"电流","水流"一样,它是以同一个方向顺序移动的过程.只不过这里流动的是字节(2进制数据).所以在IO中有输入流和输出流之分,我们理解他们…

GO语言 gin框架 简述

原文地址 基本路由 Go语言中文文档 一、简介 Gin是一个golang的轻量级web框架&#xff0c;性能不错&#xff0c;API友好。 Gin支持Restful风格的API&#xff0c;可以直接从URL路径上接收api参数或者URL参数&#xff0c;也可是使用json或者表单 数据绑定的方式接收参数。 Gin响…

152.找出峰值(力扣)

代码解决 class Solution { public:// 函数用于找到山峰元素的索引vector<int> findPeaks(vector<int>& mountain) {vector<int> result; // 用于存储山峰元素的索引// 遍历数组&#xff0c;从第二个元素到倒数第二个元素for(int i 1; i 1 < mount…

C++ | Leetcode C++题解之第117题填充每个节点的下一个右侧节点指针II

题目&#xff1a; 题解&#xff1a; class Solution { public:void handle(Node* &last, Node* &p, Node* &nextStart) {if (last) {last->next p;} if (!nextStart) {nextStart p;}last p;}Node* connect(Node* root) {if (!root) {return nullptr;}Node *…

数据结构——二叉树的基本应用

在此之前我们已经初步了解了二叉树&#xff0c;在介绍堆的基本应用时&#xff0c;我们已经具体介绍了完全二叉树的基本应用&#xff0c;本章我们介绍二叉树的基本应用&#xff0c;这个不止指的是完全二叉树&#xff0c;而是指泛型的二叉树。 二叉树的基本应用&#xff0c;由于…

NDIS协议驱动(三)

协议驱动程序源自发送请求并处理基础驱动程序的接收指示。 在单个函数调用中&#xff0c;NDIS 协议驱动程序可以在每个 NET_BUFFER_LIST 结构上发送具有多个 NET_BUFFER 结构的多个NET_BUFFER_LIST结构。 在接收路径中&#xff0c;协议驱动程序可以接收NET_BUFFER_LIST结构的列…

宝塔部署Java+Vue前后端分离项目

1. 服务器 服务器选择Linux的CentOS7的版本 2. 宝塔Linux面板 2.1 百度搜索宝塔 2.2 进去之后点击立即免费安装 2.3 选择Linux在线安装&#xff0c;输入服务器信息进行安装(也可以选择其他方式) 安装完成之后会弹一个宝塔的应用面板&#xff0c;并附带有登录名称和密码&…

Hugging face win使用教程(二)

1. 将环境迁移到win&#xff0c;可以直接下载修改好的cuda环境https://download.csdn.net/download/liangjiubujiu/89368302?spm1001.2014.3001.5503 2. 修改hugging face的缓存路径 3. 重启pycharm 4. 编写测试代码&#xff0c;注意可能由于网络链接问题&#xff0c;需要关…

OSINT 与心理学:通过开源情报进行剖析和行为分析

在不断发展的心理学领域&#xff0c;人们越来越认识到通过应用开源情报 (OSINT) 方法取得进步的潜力。OSINT 主要以其在安全和情报领域的应用而闻名&#xff0c;并且越来越多地展示其在心理分析和行为分析方面的潜力。本文探讨了 OSINT 和心理学的迷人交叉点&#xff0c;研究如…

基于BP神经网络和小波变换特征提取的烟草香型分类算法matlab仿真,分为浓香型,清香型和中间香型

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ...................................................................................... …

AURIX TC3xx单片机介绍-启动过程介绍3

如下的内容是英文为主,对于TC3xx芯片启动原理不清楚的,可以给我留言,我来解答你们的问题! 3.2.1 Reset类型识别 Reset类型的识别是用来判断上次的复位是Application Reset还是System Reset还是CPU0 Reset。基于复位的原因,启动软件会运行不同的分支逻辑。复位原因可以通…

每日两题 / 131. 分割回文串 42. 接雨水(LeetCode热题100)

131. 分割回文串 - 力扣&#xff08;LeetCode&#xff09; 数据量较小&#xff0c;考虑直接暴力&#xff0c;每次dfs&#xff1a;以bg作为左区间&#xff0c;往右遍历&#xff0c;找到一段回文串区间后&#xff0c;将回文串插入vector<string>&#xff0c;并以下一个下标…

【最优化方法】实验一 熟悉MATLAB基本功能

实验一  熟悉MATLAB基本功能 实验的目的和要求&#xff1a;在本次实验中&#xff0c;通过亲临使用MATLAB&#xff0c;对该软件做一全面了解并掌握重点内容。 实验内容&#xff1a; &#xff11;、全面了解MATLAB系统 &#xff12;、实验常用工具的具体操作和功能 学习建…

PHP:phpmyadmin 将查询数据导出csv

1、输入你的SQL查询出结果 2、查出数据以后拖到最下方【导出】 3、导出CSV

cs61B-sp21 | lab6

cs61B-sp21 | lab6 TODO 1 在 CapersRepository.java 中 static final File CAPERS_FOLDER null; // TODO Hint: look at the join // function in Utils在 Utils.java 我们找到 join 函数&#xff0c;第一个 join 的作用是将 first 和 others 连接起来形成一个路径…