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

目录

引言

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.mzph.cn/web/18366.shtml

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

相关文章

常用压力、流量单位换算表

一、压力为单位面积所承受的力 压力&#xff1a;绝对压力 、表压力 、大气压力。相互关系&#xff1a;绝对压力表压力大气压力 绝对压力:当压力表示与完全真空的差。测量处的实际压力。 表压力:当表示其气体数值与该地域大气压力的差值。 大气压力&#xff1a;由大气重量所…

基于C++11实现的手写线程池

在实际的项目中&#xff0c;使用线程池是非常广泛的&#xff0c;所以最近学习了线程池的开发&#xff0c;在此做一个总结。 源码&#xff1a;https://github.com/Cheeron955/Handwriting-threadpool-based-on-C-17 项目介绍 项目分为两个部分&#xff0c;在初版的时候&#x…

让EXCEL VBA支持鼠标滚轮,vb6 IDE鼠标滚轮插件原理

vb6 IDE鼠标滚轮插件怎么运行的(适用于VBA) 使用 Spy&#xff0c;我发现代码窗口正在获取 WM_MOUSEWHEEL 事件&#xff0c;但没有触发 WM_VSCROLL 消息。因此&#xff0c;我编写了一个简单的消息钩子&#xff0c;当它捕获鼠标滚轮事件时触发滚动事件。 我从 Spy 得知代码窗口的…

SQL数据库多层嵌套 json转sql建表语句,SQL数据库里数组里对象数据怎么创建

1. uniapp sqlite 一个数组包含对象嵌套对象通过主外键方式插入数据库&#xff1a; // 假设有一个对象数组&#xff0c;对象中包含嵌套对象 const objectsArray [{parentObject: {id: 1,name: Parent 1,// 其他父对象属性},childObject: {id: 11,parentId: 1,name: Child 1 o…

截图工具分享(Snipaste、FastStone Capture)

目录 一、背景二、Snipaste 截图工具三、FastStone Capture 截图工具 一、背景 在我们日常的学习、工作中&#xff0c;经常会需要使用到各种各样的截图场景&#xff0c;甚至有部分同学还不知道仅仅通过截图的运用就可以大大提升自己的学习效率和工作效率。在这篇文章中&#xf…

如何解决链游中可能出现的延迟或网络拥堵问题?

随着区块链技术的不断发展和普及&#xff0c;链游&#xff08;基于区块链的游戏&#xff09;作为新兴的娱乐形式&#xff0c;正逐渐走进大众的视野。然而&#xff0c;与传统游戏相比&#xff0c;链游在运行过程中可能会遇到一些特有的问题&#xff0c;其中最为突出的就是延迟和…

宝塔下应该用 Memcached 还是 Redis?

明月最近在跟几个使用宝塔面板的客户运维的时候发现不少站长不知道如何选择 Memcached 和 Redis&#xff0c;甚至都说不清楚 Memcached 或者 Redis 具体是用来干啥的&#xff1f;甚至还碰到过一个站长 Memcached 和 Redis 都安装了&#xff0c;但一个都没有用&#xff0c;就那么…

希尔排序法

希尔排序为插入排序的优化&#xff0c;即将数组分组&#xff0c;将每一组进行插入排序&#xff0c;每一组排成有序后&#xff0c;最后整体就变有序了。 上面gap2&#xff0c;即5&#xff0c;14&#xff0c;18&#xff0c;27&#xff0c;68为一组&#xff1b;13&#xff0c;20&a…

Numba 的 CUDA 示例(1/4):踏上并行之旅

按照本系列从头开始使用 Python 学习 CUDA 编程 介绍 GPU&#xff08;图形处理单元&#xff09;&#xff0c;顾名思义&#xff0c;最初是为计算机图形学开发的。从那时起&#xff0c;它们几乎在每个需要高计算吞吐量的领域都无处不在。这一进步得益于 GPGPU&#xff08;通用 G…

Java基础:基本语法(一)

Java基础&#xff1a;基本语法&#xff08;一&#xff09; 文章目录 Java基础&#xff1a;基本语法&#xff08;一&#xff09;1. 前言2. 开发环境搭建2.1 Java开发工具包下载2.2 环境变量配置2.3 Java程序的运行过程 3. 数据类型3.1 基本数据类型3.2 引用数据类型 4. 常量与变…

opencascade V3d_PositionLight V3d_SpotLight 源码学习 (位置性)光源

Positional、Spot 和 Directional Light 类的基类。 类V3d_SpotLight 创造和修改光源的衰减因子 F 决定了表面的照明&#xff1a; F 1 / (ConstAttenuation() LinearAttenuation() * Distance) 其中 Distance 是从光源到表面的距离。默认值 (1.0, 0.0) 对应最小的衰减。浓…

【做一道算一道】力扣332.重新安排行程

332.重新安排行程 给定一个机票的字符串二维数组 [from, to]&#xff0c;子数组中的两个成员分别表示飞机出发和降落的机场地点&#xff0c;对该行程进行重新规划排序。所有这些机票都属于一个从 JFK&#xff08;肯尼迪国际机场&#xff09;出发的先生&#xff0c;所以该行程必…

navicat连接过的库忘记密码

1、点击文件->导出连接 2、勾选想要知道密码的库 3、打开导出的文件搜索Password 4、复制Password解密 把下面的php代码复制到在线运行php的网站&#xff0c;替换最下面的decrypt(‘B7246A6E64D4F50A563FA20427A47991’)括号里的内容&#xff0c;然后执行php代码&#xff0…

Linux--进程间通信(1)(匿名管道)

目录 1.了解进程通信 1.1进程为什么要通信 1.2 进程如何通信 1.3进程间通信的方式 2.管道 2.1管道的初步理解 2.2站在文件描述符的角度-进一步理解管道 2.3 管道的系统调用接口&#xff08;匿名管道&#xff09; 2.3.1介绍接口函数&#xff1a; 2.3.2编写一个管道的代…

通过date命令给日志文件添加日期

一、背景 服务的日志没有使用日志工具&#xff0c;每次重启后生成新日志文件名称相同&#xff0c;新日志将会把旧日志文件冲掉&#xff0c;旧日志无法保留。 为避免因旧日志丢失导致无法定位问题&#xff0c;所以需要保证每次生成的日志文件名称不同。 二、解决 在启动时&am…

SQLI-labs-第二十六关和第二十六a关

目录 第二十六关 1、判断注入点 2、判断数据库 3、判断表名 4、判断字段名 5、获取数据库的数据 第二十六a关 第二十六关 知识点&#xff1a;绕过and、or、空格、注释符等过滤 思路 通过源代码&#xff0c;我们可以知道&#xff0c;数据库对用户的输入进行了过滤&…

【校园网网络维修】当前用户使用的IP与设备重定向地址中IP不一致,请重新认证

出现的网络问题&#xff1a;当前用户使用的IP与设备重定向地址中IP不一致&#xff0c;请重新认证 可能的原因&#xff1a; 把之前登录的网页收藏到浏览器&#xff0c;然后直接通过这个链接进行登录认证。可能是收藏网址导致的ip地址请求参数不一致。 解决方法&#xff1a; 方法…

基于JCEF实现网页资源性能分析

文章目录 1、需求2、实现代码3、运行效果 1、需求 在使用chrome浏览器访问页面时&#xff0c;浏览器自带的开发者工具可以查看页面每个资源的资源大小和加载时间。 这个功能可以让我们直接知道接口或资源的耗时情况和大小情况&#xff0c;如果存在性能问题&#xff0c;可以进…

基于springboot+vue的社区医院管理服务系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

AST反混淆|对一段非常复杂的混淆代码深度剖析与还原

关注它&#xff0c;不迷路。 本文章中所有内容仅供学习交流&#xff0c;不可用于任何商业用途和非法用途&#xff0c;否则后果自负&#xff0c;如有侵权&#xff0c;请联系作者立即删除&#xff01; 1.代码片段 ((((ld0 ((ld1 (ld1 Uint8Array) && undefined…