动态规划之买卖股票大集合

目录

引言

1.只能进行一次买卖股票(最多只能买一股股票)

2.可以进行多次股票买卖,且没有手续费(最多只能买一股股票)

3.可以进行多次股票买卖,但是有冷冻期,无手续费(最多只能买一股股票)

4.可以进行多次股票买卖,但是有手续费(最多只能买一股股票)


引言

作为动态规划中最常见的一类问题,买卖股票问题的思想也时常会出现在动态规划的题目中,买卖股票主要分为两大类,一种是有限制条件的,另一种是没有限制条件的

买卖股票问题主要的思路是用一个二维dp数组去存储是否持有股票的两个状态

比如说dp[ i ][ 0 ]表示就的就是在第i天持有股票的最大金额

dp[ i ][ 1 ]表示的就是在第i天没有持有股票的最大金额

然后我们就可以写出递推关系式

例如对于

(1)只能买一次股票来说

dp[i][0]=max(dp[i-1][0],-p[i]);   
dp[i][1]=max(dp[i-1][1],dp[i-1][0]+p[i]);

对于持有股票来说,由于只能购买一次,所以对于购买股票的时候,初始金额一定为0,因此我们的持有的状态只能由前一天持有的最小花费的状态和本天购买的花费的较小值推出来

不持有的状态是由前一天包括之前卖出股票的最大价值和在本天卖出股票的价值的较大者推出

(2)可以买卖多次股票

唯一的不同点在于购买的时候,因为可以买卖多次,因为购买股票的初始金额必然是有可能为非0的因此,我们要通过前一天包括之前不持有股票的状态推出今天持有股票的最大状态

dp[i][0]=max(dp[i-1][0],dp[i-1][1]-p[i]);//唯一不同点

dp[i][1]=max(dp[i-1][1],dp[i-1][0]+p[i]);

当然了,这边的二维数组也可以将空间压缩成1维dp数组,让其变成一个滚动数组,从而降低空间复杂度

dp[ 0 ]指的就是持有股票的状态

dp[ 1 ]指的就是不持有股票的状态

1.只能进行一次买卖股票(最多只能买一股股票)

只能买卖一次 持有状态 不能由之前不持有的利润累加,就是持有状态永远都是0减去今天的价格

来看一道例题

传送门——买卖股票的最佳时机

题解:很标准的买卖股票问题,只能买卖一次,因此我们就可以用动规五部曲去完成这道题

1.明确dp数组的含义,首先就是dp[ i ][ 0 ]表示的是 对于第i天来说,持有股票的最大金额

dp[ i ][ 1 ]表示的是 对于第i天来说,不持有股票的最大金额

 2.状态转移方程:dp[i][0]=max(dp[i-1][0],-p[i]);   
dp[i][1]=max(dp[i-1][1],dp[i-1][0]+p[i]);

3.初始化dp[1][0]=-p[1]//p[1]指的是第p天股票的价值,dp[1][1]=0;

4.遍历顺序,第一天遍历到第n天就行

二维dp数组:

#include<bits/stdc++.h>
using namespace std;int n;
int p[105];
int dp[105][2];
//dp数组的含义
//dp[i][0]表示的是在第i天拥有股票的最大价值,可以是在第i天买的股票,也可以是在之前买的
//说白了dp[i][0]统计的就是在第i天及之前,购进股票的最小花费 
//dp[i][1]表示的是在第i天没有股票的最大价值,既可以是没有买,也可以是卖了又买了
//这个用于统计的就是买卖股票的最大价值 
int main()
{cin>>n;for(int i=1;i<=n;i++)cin>>p[i];dp[1][0]=-p[1];//在第一天拥有股票的最大价值 dp[1][1]=0;//在第一天没有拥有股票的最大价值for(int i=2;i<=n;i++){dp[i][0]=max(dp[i-1][0],-p[i]);dp[i][1]=max(dp[i-1][1],dp[i-1][0]+p[i]);}cout<<dp[n][0]<<"\n";cout<<dp[n][1];return 0;
}

一维dp数组: 

//一维dp数组
#include<bits/stdc++.h>
using namespace std;
int n;
int p[105];
int dp[2];//dp[0]表示持有股票的状态,dp[1]指的是没持有股票的状态int main()
{cin>>n;for(int i=1;i<=n;i++){cin>>p[i];}dp[0]=-p[1];dp[1]=0;for(int i=1;i<=n;i++){dp[0]=max(dp[0],-p[i]);dp[1]=max(dp[1],dp[0]+p[i]);}cout<<dp[1];return 0;} 

2.可以进行多次股票买卖,且没有手续费(最多只能买一股股票)

传送门——买卖股票的最佳时机2

题解:也是很经典的股票买卖问题,并且是可以买卖多次,且不需要手续费的,唯一和·上面不同的就是去推不持有股票的状态发生了一些变化,其他的一样,包括dp数组的含义啊,遍历顺序啊,初始化啊,什么的,都是一样的

二维dp数组:

#include<bits/stdc++.h>
using namespace std;
int n;
int p[105];
int dp[105][2];int main()
{cin>>n;for(int i=1;i<=n;i++)cin>>p[i];dp[1][0]=-p[1];dp[1][1]=0;for(int i=2;i<=n;i++){dp[i][0]=max(dp[i-1][0],dp[i-1][1]-p[i]);//唯一不同点//因为原来只能购买一次,所以计算最大的肯定是-p[i],但是现在可以买卖多次,就说明初始值不一定为0,我们的初始值为dp[i-1][1]的值 dp[i][1]=max(dp[i-1][1],dp[i-1][0]+p[i]);}cout<<dp[n][1];return 0;
}

 一维的dp数组:

#include<bits/stdc++.h>
using namespace std;
int n;
int p[105];
int dp[2];//dp[0]持有股票,dp[1]不持有股票 int main()
{cin>>n;for(int i=1;i<=n;i++)cin>>p[i];dp[0]=-p[1];dp[1]=0;for(int i=1;i<=n;i++){dp[1]=max(dp[1],dp[0]+p[i]);dp[0]=max(dp[0],dp[1]-p[i]);}cout<<dp[1];return 0;
}

3.可以进行多次股票买卖,但是有冷冻期,无手续费(最多只能买一股股票)

这个相比于正常股票买卖问题在不持股状态分的更加细致,对于不持股状态可以分为,因为卖出的冷冻期导致不持股,或者是不是冷冻期导致的不持股,再算上持股状态,因此总共有三个状态,我们可以将其列举出来

0:持股状态

1:不是因为冷冻期而导致的不持股

2:因为冷冻期而导致的不持股

分别写出各自的状态转移方程

对于持股状态来说,他只能由之前的持股状态不是冷冻期的不持股,买第i天的股票转移过来

dp[i][0]=max(dp[i-1][0],dp[i-1][1]-p[i]);

对于不是因为冷冻期而导致的不持股来说,他只能由之前的非冷冻期不持股冷冻期不持股推出来

(因为一旦卖出就要进入冷冻期,没办法由0推出1)

dp[i][1]=max(dp[i-1][1],dp[i-1][2]);

对于因为冷冻期而导致的不持股来说,他只能由之前的持股状态卖出得到

dp[i][2]=dp[i-1][0]+p[i]; 

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

#include<bits/stdc++.h>
using namespace std;
int n;
int p[105];
int dp[105][3];
//0:持股状态
//1:不是因为卖出股票而导致的不持股 
//2:因为卖出股票而导致的不持股 int main()
{cin>>n;for(int i=1;i<=n;i++)cin>>p[i];dp[1][0]=-p[1];dp[1][1]=0;dp[1][2]=0;//第一天肯定不能是冷冻期,必然是0 for(int i=2;i<=n;i++){dp[i][0]=max(dp[i-1][0],dp[i-1][1]-p[i]);dp[i][1]=max(dp[i-1][1],dp[i-1][2]);dp[i][2]=dp[i-1][0]+p[i]; }cout<<max(dp[n][1],dp[n][2]);return 0;
}

4.可以进行多次股票买卖,但是有手续费(最多只能买一股股票)

这个只需要在dp[1]的地方改一下即可,就是在获取到赚的钱的时候顺带减一下手续费就ok,难度比第三个低很多

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

题解:和第二个差不多,只不过多加了个手续费,状态转移方程变为dp[1]=max(dp[1],dp[0]+p[i]-fee);

#include<bits/stdc++.h>
using namespace std;
int n;
int p[105];
int dp[2];//dp[0]持有股票,dp[1]不持有股票 int main()
{cin>>n;for(int i=1;i<=n;i++)cin>>p[i];int fee=0;cin>>fee;dp[0]=-p[1];dp[1]=0;for(int i=1;i<=n;i++){dp[1]=max(dp[1],dp[0]+p[i]-fee);dp[0]=max(dp[0],dp[1]-p[i]);}cout<<dp[1];return 0;
}

 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电脑卡顿---WINDOWS任何关闭应用开机自启动

打开windows11的控制面板&#xff0c;点击应用&#xff0c;点击启动 如下图圈出来的地方就是开机自启动的开关按键。

Android 11 Audio音频系统配置文件解析

在AudioPolicyService的启动过程中&#xff0c;会去创建AudioPolicyManager对象&#xff0c;进而去解析配置文件 //frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientIn…

如何在生产环境中以非 Root 用户启动 Kafka

目录 如何在生产环境中以非 Root 用户启动 Kafka1. 创建 Kafka 用户2. 设置目录权限3. 配置 systemd 服务文件4. 启动和启用 Kafka 服务5. 验证 Kafka 服务经验总结 为了在生产环境中以非 root 用户&#xff08;如 kafka 用户&#xff09;启动 Kafka&#xff0c;您需要确保 Ka…

【软件测试】bug篇|软件测试的生命周期|描述bug的要素|bug的级别|bug的生命周期|高频面试题:与开发产⽣争执怎么处理

目录 一、软件测试的⽣命周期 二、BUG 2.1 bug的概念 2.2 描述bug的要素 2.3 bug级别 2.4 bug的⽣命周期 &#x1f4a1;2.5 与开发产⽣争执怎么办&#xff08;⾼频考题&#xff09; &#x1f4a1; 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&…

Unity实现首行缩进两个字符

效果 在Unity中如果想实现首行缩进两个字符&#xff0c;你会发现按空格是没法实现的。 实现原理&#xff1a;用空白的透明的字替代原来的位置。 代码&#xff1a; <color#FFFFFF00>XXX</color> 赶紧去试试吧&#xff01;

CASS11自定义宗地图框

1、找到CASS11的安装路径&#xff0c;找到如下文件夹&#xff1a; 2、打开【report】文件夹&#xff0c;如下&#xff1a; 3、打开其中一个压缩包&#xff0c;如【标准宗地图】压缩包&#xff0c;结果如下&#xff1a; 4、打开后&#xff0c;将其另存为到桌面&#xff0c;随后关…

新书推荐:7.5 goto、break、continue语句

本节必须掌握的知识点&#xff1a; 示例二十六 代码分析 汇编解析 示例二十七 代码分析 汇编解析 7.5.1 示例二十六 ■goto语句&#xff1a;无条件转移语句。 语法格式&#xff1a; goto label; label : 代码; ●语法解析&#xff1a; 执行到goto语句时&#xff0c;则无…

释放 OSINT 的力量:在线调查综合指南

开源情报 (OSINT) 是从公开信息中提取有价值见解的艺术。无论您是网络安全专业人士、道德黑客还是情报分析师&#xff0c;OSINT 都能为您提供先进的技术&#xff0c;帮助您筛选海量的数字数据&#xff0c;发现隐藏的真相。 在本文中&#xff0c;我们将深入研究大量的OSINT 资源…

项目十三:搜狗——python爬虫实战案例

根据文章项目十二&#xff1a;简单的python基础爬虫训练-CSDN博客的简单应用&#xff0c;这一次来升级我们的技术&#xff0c;那么继续往下看&#xff0c;希望对技术有好运。 还是老样子&#xff0c;按流程走&#xff0c;一条龙服务&#xff0c;嘿嘿。 第一步&#xff1a;导入…

12.2 通道-阻塞与流程控制、通道型函数、退出通道

阻塞与流程控制 通常在并发程序中要尽力避免阻塞式操作&#xff0c;但有时又需要让代码暂时处于阻塞状态&#xff0c;以等待某种条件、信号或数据&#xff0c;然后再继续运行。 对于无缓冲通道&#xff0c;试图从无人写入的通道中读取&#xff0c;或者向无人读取的通道中写入…

【Sql Server】随机查询一条表记录,并重重温回顾下自定义函数的封装和使用

大家好&#xff0c;我是全栈小5&#xff0c;欢迎来到《小5讲堂》。 这是《Sql Server》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 前言随机查询语…

MongoDB数据库(10亿条数据)清理策略: 自动化过期数据删除实战

1、引言 随着应用程序和业务数据的持续增长&#xff0c;有效地管理数据库存储空间成为维护系统性能的关键。在MongoDB这类NoSQL数据库中&#xff0c;定期清理过期数据变得尤为重要&#xff0c;这不仅能释放宝贵的存储资源&#xff0c;还能优化查询性能&#xff0c;确保数据库运…

5,串口编程---实现简单的用串口发送接收数据

单片机通过串口向PC机发送数据 PC机通过串口接收单片机发过来的数据 1.UART和USART的区别&#xff1a; USART支持同步通信方式,可以通过外部时钟信号进行同步传输,而UART仅支持异步通信方式 本开发板STM32F103ZET6有5个串口&#xff0c;用串口1作调试串口&#xff0c;因为串…

让AI学相机对焦: Learning to AutoFocus

前言 分析来自谷歌发表在 CVPR 2020 上的论文 Learning to Autofocus &#xff1a;https://arxiv.org/pdf/2004.12260 目前网上对这篇论文的分析较少&#xff0c;有的分析并没有指出关键点&#xff0c;如&#xff1a;论文解读&#xff1a; Learning to AutoFocus-CSDN博客&am…

spring常用知识点

1、拦截器和过滤器区别 1. 原理不同&#xff1a; 拦截器是基于java的反射机制&#xff0c;而过滤器采用责任链模式是基于函数回调的。 2. 使用范围不同&#xff1a; 过滤器Filter的使用依赖于Tomcat等容器&#xff0c;导致它只能在web程序中使用 拦截器是一个Sping组件&am…

jQuery 常用API

一、jQuery 选择器 1、jQuery 基础选择器 原生JS获取元素方式很多&#xff0c;很杂&#xff0c;而且兼容性情况不一致&#xff0c;因此jQuery给我们做了封装&#xff0c;使获取元素统一标准 2、jQuery 层级选择器 3、隐式迭代 遍历内部 DOM 元素&#xff08;伪数组形式存储&am…

存储+调优:存储-IP-SAN-EXTENSION

存储调优&#xff1a;存储-IP-SAN-EXTENSION 文件系统的锁标记 GFS&#xff08;锁表空间&#xff09; ----------- ------------ ------------- 节点 | ndoe1 | | node2 | | node3 | ---------- ------…

STM32建立工程问题汇总

老版本MDK&#xff0c;例如MDK4 工程内容如下&#xff1a; User文件夹中存放main.c文件&#xff0c;用户中断服务函数&#xff08;stm32f1xx.it.c&#xff09;&#xff0c;用户配置文件&#xff08;stm32f1xx_hal_conf.h&#xff09;等用户程序文件&#xff0c;或者mdk启动程序…

Spring Cloud Gateway 网关

一. 什么是网关&#xff08;Gateway&#xff09; 网关就是一个网络连接到另一个网络的关口。 在同一个项目或某一层级中&#xff0c;存在相似或重复的东西&#xff0c;我们就可以将这些相似重复的内容统一提取出来&#xff0c;向前或向后抽象成单独的一层。这个抽象的过程就是…

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

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