【动态规划】简单多状态

news2024/11/29 4:27:25

文章目录

  • 动态规划(简单多状态)
    • 1. 按摩师
    • 2. 打家劫舍 ||
    • 3. 删除并获得点数
    • 4. 粉刷房子
    • 5. 最佳买卖股票时机含冷冻期
    • 6. 买卖股票的最佳时机含手续费
    • 7. 买卖股票的最佳时机 |||
    • 8. 买卖股票的最佳时机 IV

动态规划(简单多状态)

1. 按摩师

题目链接

  1. 状态表示

    dp[i]表示到i位置的时候预约的最大时长。但是这个题目我们可以选择接或不接。因此可以继续划分为两个子状态:

    • f[i]表示:到i位置时接受的最大时长
    • g[i]表示:到i位置时不接受的最大时长
  2. 状态转移方程

    2vu4cjw7da-1690362953455.png

  3. 初始化

    因为这个题目比较简单,所以不需要使用虚拟节点的方法,初始化是为了后面填表的时候不越界

    f[0] = nums[0], g[0] = 0

  4. 填表

    从左到右

  5. 返回值

    接受最后一个或者不接受的最大值

AC代码:

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

2. 打家劫舍 ||

题目链接

分析:

由于房间是连续的,也就是一个环,因此可以分类讨论:

  • 偷第一个时,第二个和最后一个不能偷
  • 不偷第一个,可以偷第二个和最后一个

因此只需要两种情况的最大值就可以

  1. 状态表示

    dp[i]表示偷到i时的最大金额,但是依然可以划分为两种情况偷或不偷

    f[i]表示偷i时的最大金额

    g[i]表示不偷i时的最大金额

  2. 状态转移方程

    qx81yjpg3g-1690364303443.png

  3. 初始化

    保证后续的填表不越界

  4. 填表

    从左到右,两个一起填

  5. 返回值

    最大值

AC代码:

class Solution 
{
public:
    int rob(vector<int>& nums) 
    {
        int x = 0, y = 0;
        int n = nums.size();
        x += nums[0];
        x += recursion(2, n - 2, nums);
        y += recursion(1, n - 1, nums);
        return max(x, y);
    }
    int recursion(int left, int right, vector<int> &v)
    {
        if (left > right) return 0;
        int n = v.size();
        vector<int> f(n);
        auto g = f;
        f[left] = v[left]; // 初始化
        for (int i = left + 1; i <= right; i++)
        {
            f[i] = g[i - 1] + v[i];
            g[i] = max(g[i - 1], f[i - 1]);
        }
        return max(f[right], g[right]);
    }
};

3. 删除并获得点数

题目链接

分析:我们把所有数字的点数之和,放到一个数组当中,在进行一次打家劫舍就可以了

把原数组转换成一个新数组,新数组的下标i所对应的值为原数组的元素i在原数组中数字的总和,比如原数组[2, 2, 3, 3, 3, 4],转换为新数组就是[0, 0, 4, 9, 4]。在新数组中,下标0和1表示在原数组中没有0和1这两个数,新数组下标2的值是4,表示在原数组中,所有2的总和是4。转换的目的就是可以从新数组中得到删除nums[i]而得到的点数,也就是可以打劫的金额。因为删除nums[i]后,还要删除nums[i] + 1nums[i] - 1,在新数组中就意味着不能取相邻的元素,不能取相邻的元素和打家劫舍也是一样的。接下来就可以使用打家劫舍的方式解答了

AC代码:

class Solution 
{
public:
    const int N = 10001;
    int deleteAndEarn(vector<int>& nums) 
    {
        vector<int> arr(N);
        for (auto e : nums) arr[e] += e;
        vector<int> g(N);
        auto f = g;
        for (int i = 1; i < N; i++)
        {
            f[i] = g[i - 1] + arr[i];
            g[i] = max(g[i - 1], f[i - 1]);
        }
        return max(g[N - 1], f[N - 1]);
    }
};

4. 粉刷房子

题目链接

  1. 状态表示

    dp[i]表示到i时,所需的最少费用。但是到i的时候可以有三种情况我们需要分三个子状态

    dp[i][0], dp[i][1], dp[i][2]

  2. 状态转移方程

    wrmwgl7sbc-1690365960472.png

  3. 初始化

    采用虚拟节点的方式

  4. 填表

  5. 返回值

    返回三个表中的最小值

AC代码:

class Solution 
{
public:
    int minCost(vector<vector<int>>& costs) 
    {
        // 0: 红色 1:蓝色 2:绿色
        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];
        }
        int ret = INT_MAX;
        for (int i = 0; i < 3; i++)
        {
            ret = min(ret, dp[n][i]);
        }
        return ret;
    }
};

5. 最佳买卖股票时机含冷冻期

题目链接

  1. 状态表示

    dp[i]表示到i位置时的最大利润,但是到达i位置的时候仍然有3种子状态

    • dp[i][0],表示i过后处于买入状态
    • dp[i][1], 表示i过后处于可交易状态
    • dp[i][2],表示i过后处于冷冻期状态
  2. 状态转移方程

    像这种状态之间可以相互转换的,我们可以采用如下方法分析:

    bh40p1zbcb-1690367957450.png

  3. 初始化

    dp[0][0] = -prices[0], dp[0][1] = 0, dp[0][2] = 0

  4. 填表

    三张表同时填

  5. 返回值

    返回三中状态最后的最大值

AC代码:

class Solution 
{
public:
    int maxProfit(vector<int>& prices) 
    {
        int n = prices.size();
        vector<vector<int>> dp(n, vector<int>(3));
        dp[0][0] = -prices[0];
        for (int i = 1; i < n; i++)
        {
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]);
            dp[i][1] = max(dp[i - 1][1], dp[i - 1][2]);
            dp[i][2] = dp[i - 1][0] + prices[i];
        }
        return max(max(dp[n - 1][0], dp[n - 1][1]), dp[n - 1][2]);
    }
};

6. 买卖股票的最佳时机含手续费

题目链接

  1. 状态表示

    dp[i]表示到i位置的时候,最大的利润但是到i位置的时候是有两种状态的

    dp[i][0]:表示是买入状态

    dp[i][1]表示卖出状态

  2. 状态转移方程

    ogyovzrz17-1690372796443.png

  3. 初始化

    刚开始如果是买入状态dp[0][0] = -prices[0]

  4. 填表

  5. 返回值

AC代码:

class Solution 
{
public:
    int maxProfit(vector<int>& prices, int fee) 
    {
        int n = prices.size();
        vector<vector<int>> dp(n, vector<int>(2));
        dp[0][0] = -prices[0];
        for (int i = 1; i < n; i++)
        {
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]);
            dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i] - fee);
        }
        return max(dp[n - 1][0], dp[n - 1][1]);
    }
};

7. 买卖股票的最佳时机 |||

题目链接

  1. 状态表示

    dp[i]表示到i位置的最大利润,但是还分为几个状态

    f[i][j]表示到i是第j次买入的最大利润

    g[i][j]表示到i是第j次买入的最大利润

  2. 状态转移方程

    zrwwmb104n-1690374918443.png

  3. 初始化

    f[0][0] = -prices[0], g[0][0] = 0

  4. 填表

    从上往下,每一行从左到右

  5. 返回值

    卖出状态最后的几个中的最大值

AC代码:

class Solution 
{
public:
    const int N = 0x3f3f3f3f;
    int maxProfit(vector<int>& prices) 
    {
        int n = prices.size();
        vector<vector<int>> f(n, vector<int>(3, -N));
        auto g = f;
        f[0][0] = -prices[0], g[0][0] = 0;
        for (int i = 1; i < n; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                f[i][j] = max(f[i - 1][j], g[i - 1][j] - prices[i]);
                g[i][j] = g[i - 1][j];
                if (j - 1 >= 0) g[i][j] = max(g[i][j], f[i - 1][j - 1] + prices[i]);
            }
        }
        int ret = 0;
        for (int i = 0; i < 3; i++)
        {
            ret = max(ret, g[n - 1][i]);
        }
        return ret;
    }
};

8. 买卖股票的最佳时机 IV

题目链接

  1. 状态表示

    还是分为两个子状态

    f[i][j]表示到i位置买入状态第j次买股票的最大利润

    g[i][j]表示到i位置卖出状态第j次买股票的最大利润

  2. 状态转移方程

    image-20230726205442099

  3. 初始化

    f[0][0] = -prices[0], g[0][0] = 0

  4. 填表

    从上到下,从左到右

  5. 返回值

    返回所有行的最大值

AC代码:

class Solution {
public:
    const int N = 0x3f3f3f3f;
    int maxProfit(int k, vector<int>& prices) {
        int n = prices.size();
        vector<vector<int>> f(n, vector<int>(k + 1, -N));
        auto g = f;
        f[0][0] = -prices[0], g[0][0] = 0;
        for (int i = 1; i < n; i++)
        {
            for (int j = 0; j <= k; j++)
            {
                f[i][j] = max(f[i - 1][j], g[i - 1][j] - prices[i]);
                g[i][j] = g[i - 1][j];
                if (j - 1 >= 0) g[i][j] = max(g[i][j], f[i - 1][j - 1] + prices[i]);
            }
        }
        int ret = 0;
        for (int i = 0; i <= k; i++)
        {
            ret = max(ret, g[n - 1][i]);
        }
        return ret;
    }
};

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

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

相关文章

dp算法篇Day12

“我悲喜都&#xff0c;只换来这一场无声的野火。” 56、完全平方数 (1) 题目解析 ​​​​​​ 把题目解释到了这个份上&#xff0c;你很难不把思路转移到考虑 "背包问题上"。 (2) 算法原理 class Solution { public:int numSquares(int n) {int m sqrt(n);vec…

【Python基础】VS2019中使用Python及安装Python包

【Python基础】VS2019中使用Python及安装Python包 文章目录 前言一、VS2019中安装Python环境二、Python环境变量配置三、安装Python包总结 前言 要使用Python语言来写一些程序&#xff0c;使用哪个IDE是个问题&#xff0c;若是专业开发Python&#xff0c;PyCharm无疑是最佳选择…

RTI无线电层析成像Matlab仿真数据生成

文章目录 概述初始化环境参数逆面积椭圆模型 概述 无线电层析成像是一种通过获取一定区域内多对相对固定的无线通信节点间的某种测量数据后,按照一定的数学处理方法,对区域内的障碍物目标以图像的形式 展现出来的成像技术。 开山之作&#xff1a; J. Wilson and N. Patwari, …

【小白必看】Python爬虫实战:获取阴阳师网站图片并自动保存

文章目录 前言导入模块伪装自己发送请求获取地址列表获取所有背景的地址创建文件夹保存图片文件完整代码运行效果部分图片展示结束语 前言 本文介绍了一个使用Python编写的程序&#xff0c;用于获取指定网页的背景图片并保存到本地。在程序中使用了requests模块发送HTTP请求&a…

FCPX插件-15组金色华丽粒子特效闪耀动画 Awards Backgrounds

Awards Backgrounds是fcpx上一个很棒的电影级效果插件&#xff0c;Awards Backgrounds 包含15组金色华丽粒子特效闪耀动画&#xff0c;可以为您的作品创建豪华的背景或叠加特效&#xff01;包含各种带有可编辑颜色的下落闪闪发光粒子的场景。用于展示奖项提名者、优雅的表演、祝…

【C++】开源:Redis数据库配置与使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍Redis数据库配置与使用。 无专精则不能成&#xff0c;无涉猎则不能通。。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c…

Emacs之改造最快文本搜索工具ripgrep(一百一十九)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

微服务远程调用openFeign简单回顾(内附源码示例)

目录 一. OpenFeign简介 二. OpenFeign原理 演示使用 provider模块 消费者模块 配置全局feign日志 示例源代码: 一. OpenFeign简介 OpenFeign是SpringCloud服务调用中间件&#xff0c;可以帮助代理服务API接口。并且可以解析SpringMVC的RequestMapping注解下的接口&#x…

Android12之快速查找静态注册jni函数方法(一百六十一)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

C++初阶--C++入门

目录 前言C关键字命名空间命名空间的定义命名空间的使用加命名空间名称及作用域限定符使用using namespace 命名空间名称引入使用using将命名空间中的成员引入 C的输入与输出缺省参数全缺省半缺省参数 函数重载参数类型不同参数个数不同参数类型顺序不同 引用引用特性 常引用使…

可视化bi工具datart部署到k8s

目录 1. 前言 2. 安装 2.1 mysql初始化 2.2 datart配置文件持久化 2.3 文件挂载 2.4 部署 3. 登录及创建管理帐号 1. 前言 datart 是新一代数据可视化开放平台&#xff0c;支持各类企业数据可视化场景需求&#xff0c;如创建和使用报表、仪表板和大屏&#xff0c;进行可视…

Python面向对象(三)(继承、封装)

面向对象的三大特性 面向对象编程&#xff0c;是许多编程语言都支持的一种编程思想。 简单理解是&#xff1a;基于模板&#xff08;类&#xff09;去创建实体&#xff08;对象&#xff09;&#xff0c;使用对象完成功能开发。 面向对象包含3大主要特性&#xff1a; 封装 封…

ssl证书安装后还是显示不安全怎么办?解决办法来了

ssl证书安装后还是显示不安全怎么办&#xff1f;一般网站在部署安装ssl证书之后&#xff0c;浏览器的不安全显示就会消除。但有时候&#xff0c;在证书安装完成后&#xff0c;浏览器仍然会出现不安全提示&#xff0c;这时候我们可以按照以下的步骤一一排查解决。 1、确认安装的…

numpy广播机制介绍

广播 广播机制的意义&#xff1a;广播描述了在算术运算期间NumPy如何处理具有不同形状的数组。受某些约束条件的限制&#xff0c;较小的数组会在较大的数组中“广播”&#xff0c;以便它们具有兼容的形状。 在对两个数组进行操作时&#xff0c;NumPy按元素对它们的形状进行比…

UE5.1移动端PreintegratedSkinBxDF解析

Part 1 头文件 MobileBasePassPixelShader.usf 主要看Main函数&#xff1a; #if MOBILE_MULTI_VIEWResolvedView ResolveView(BasePassInterpolants.MultiViewId); #elseResolvedView ResolveView(); #endif这玩意Shader文件找不到&#xff0c;感觉是个全局变量的东西。万幸…

【JDK新特性】必会_Stream API

【必看】原创声明&#xff1a;转载请注明作者 & 文章来源&#xff1a;都在用Stream流&#xff1f; ​​​​​​​ hello&#xff0c;我是小索奇&#xff0c;这次讲解JDK 8新特性的重点&#xff01;Stream流&#xff0c;到后期学习框架时候你会发现大量的Stream流出现&…

波奇学C++:写实拷贝,_buf数组

我们知道当自定义对象如果在堆上开空间&#xff0c;那么拷贝构造时会深拷贝&#xff0c;深拷贝会加大内存开销&#xff0c;用写实拷贝(也叫延迟拷贝)可以在深浅拷贝中取得平衡。 浅拷贝问题&#xff1a; 析构两次 一个对象修改会影响另一个 用引用计数来解决析构问题 拷贝构造时…

商品库存管理系统设计与实现(Vue+SpringBoot+MySQL)

一、项目背景 当今&#xff0c;我国科技发展日新月异&#xff0c;各类企业迅速崛起&#xff0c;商品类型日益繁多&#xff0c;产品数量急剧增加&#xff0c;企业经营模式越来越多样&#xff0c;信息处理量不断加大&#xff0c;对库存管理提出了更高的要求。通过本系统&#xff…

[详细教程+渠道对接+实战陪跑社区]抖音超火小说推文新玩法

科思创业汇 大家好&#xff0c;这里是科思创业汇&#xff0c;一个轻资产创业孵化平台。赚钱的方式有很多种&#xff0c;我希望在科思创业汇能够给你带来最快乐的那一种&#xff01; 本人为科思创业汇&#xff0c;分享网络项目案例&#xff01; 是啊&#xff0c;公益活动又来…

白话机器学习笔记(二)学习分类

分类用图形来解释&#xff0c;把他想象为有大小有方向带箭头的向量。 设权重向量为 w w w&#xff0c;虚线为使权重向量称为法线向量的直线。 直线的表达式为&#xff1a; w ⋅ x 0 w\cdot x0 w⋅x0 (两个向量的内积) 也可写为&#xff1a; w ⋅ x ∑ i 1 n w i x i w 1…