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

目录

引言

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

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Xunsearch:实现拼音搜索和中文分词功能

首先我们需要安装xunsearch扩展库&#xff0c;参考 1、设置分词器和拼音搜索功能 在创建Xunsearch对象后&#xff0c;可以设置相应的分词器和拼音搜索功能。以下代码示例演示了如何设置分词器和拼音搜索功能&#xff1a; $index $xunsearch->index; $index->setToken…

Cesium For Unity 在Unity中无法下载的问题

Unity 下载失败&#xff0c;提供百度网盘“com.cesium.unity-1.10.0.tgz”下载链接 链接&#xff1a;https://pan.baidu.com/s/1PybXQ8EvkRofOKD6rSN66g?pwd1234 提取码&#xff1a;1234 导入方法&#xff1a; 1.打开PackageManager;Window-PackageManager 2.在PackageMan…

Leetcode621. 任务调度器

Every day a Leetcode 题目来源&#xff1a;621. 任务调度器 类似题目&#xff1a;1953. 你可以工作的最大周数 解法1&#xff1a;贪心 本质上来说&#xff0c;我们需要构造一个尽量短的&#xff0c;相同元素间隔 > (n1) 的序列。 用一个数组 cnt 统计每个任务的次数。…

【论文阅读笔记】The Google File System

1 简介 Google File System (GFS) 是一个可扩展的分布式文件系统&#xff0c;专为快速增长的Google数据处理需求而设计。这篇论文发表于2003年&#xff0c;此前已在Google内部大规模应用。 GFS不仅追求性能、可伸缩性、可靠性和可用性等传统分布式文件系统的设计目标&#xf…

如何使用 Connector API 将数据提取到 Elasticsearch Serverless 中

作者&#xff1a;来自 Elastic Jedr Blaszyk Elasticsearch 支持一系列摄取方法。 其中之一是 Elastic Connectors&#xff0c;它将 SQL 数据库或 SharePoint Online 等外部数据源与 Elasticsearch 索引同步。 连接器对于在现有数据之上构建强大的搜索体验特别有用。 例如&…

新火种AI|警钟长鸣!教唆自杀,威胁人类,破坏生态,AI的“反攻”值得深思...

作者&#xff1a;小岩 编辑&#xff1a;彩云 在昨天的文章中&#xff0c;我们提到了谷歌的AI Overview竟然教唆情绪低迷的网友“从金门大桥跳下去”。很多人觉得&#xff0c;这只是AI 模型的一次错误判断&#xff0c;不会有人真的会因此而照做。但现实就是比小说电影中的桥段…

Linux shell编程学习笔记51: cat /proc/cpuinfo:查看CPU详细信息

0 前言 2024年的网络安全检查又开始了&#xff0c;对于使用基于Linux的国产电脑&#xff0c;我们可以编写一个脚本来收集系统的有关信息。对于中央处理器CPU比如&#xff0c;我们可以使用cat /proc/cpuinfo命令来收集中央处理器CPU的信息。 1. /proc/cpuinfo 保存了系统的cpu…

【学习心得】PyTorch的知识要点复习(持续更新)

PyTorch知识要点复习&#xff0c;目的是为了巩固PyTorch基础、快速回顾、深化理解PyTorch框架。这篇文章会持续更新。 一、本文的一些说明 知识点梳理&#xff1a;我将PyTorch的核心概念和高级技巧进行了系统化的整理&#xff0c;从基础的张量操作到复杂的模型构建与训练。这样…

拉普拉斯IPO:科技与产业深度融合,实现业务领域延展

我国拥有全球最具竞争优势的光伏产业链&#xff0c;基于降本增效的需求&#xff0c;光伏产业对于技术革新具有持续的需求。拉普拉斯新能源科技股份有限公司&#xff08;以下简称“拉普拉斯”&#xff09;凭借深厚的技术积累&#xff0c;以及对光伏产业深刻的理解&#xff0c;聚…

【数据结构】AVL树——平衡二叉搜索树

个人主页&#xff1a;东洛的克莱斯韦克-CSDN博客 祝福语&#xff1a;愿你拥抱自由的风 目录 二叉搜索树 AVL树概述 平衡因子 旋转情况分类 左单旋 右单旋 左右双旋 右左双旋 AVL树节点设计 AVL树设计 详解单旋 左单旋 右单旋 详解双旋 左右双旋 平衡因子情况如…

基于ViutualBox+Ubuntu(Linux)的开发环境搭建

实际在选择虚拟机的时候纠结了要用virualbox还是vmware&#xff0c;初步比较结果&#xff1a; 1.virualbox能够使用vmware的硬盘格式&#xff0c;因此可以自由选择。 2.都能够实现主机和宿主机之间的文件夹共享。 3.virualbox是自由软件&#xff0c;vmware是商业软件。 在功能上…

Matplotlib 实践指南:图形样式、风格与标记探索

目录 前言 第一点&#xff1a;导入模块 第二点&#xff1a;创建二维图 第三点&#xff1a;创建统计图 总结 前言 Matplotlib 是一个强大的数据可视化库&#xff0c;可用于创建各种类型的图形。在本文中&#xff0c;我们将研究如何在 Matplotlib 中设置图形的颜色、风格和标记…

CANDela studio之CDDT与CDD

CDDT有更高的权限&#xff0c;作为模板规范CDD文件。 CDD可修改的内容比CDDT少。 CDDT根据诊断协议提供诊断格式&#xff0c;主要就是分类服务和定义服务&#xff0c;一般是OEM释放&#xff0c;然后由供应商细化成自己零部件的CDD文件。 在这里举个例子&#xff0c;OEM在CDDT…

Dubbo生态之初识分布式事务

1.分布式事务简介 传统的关系型数据库只能保证单个数据库中多个数据表的事务特性。一旦多个SQL操作涉及到多个数据库&#xff0c;这类的事务就无法解决跨库事务问题。在传统架构下&#xff0c;这种问题出现的情况非常少&#xff0c;但是在分布式微服务架构中&#xff0c;分布式…

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

题目&#xff1a; 题解&#xff1a; func connect(root *Node) *Node {start : rootfor start ! nil {var nextStart, last *Nodehandle : func(cur *Node) {if cur nil {return}if nextStart nil {nextStart cur}if last ! nil {last.Next cur}last cur}for p : start; …

NDIS协议驱动(四)

NDIS 定义对象标识符 (OID) 值&#xff0c;以标识适配器参数&#xff0c;其中包括设备特征、可配置设置和统计信息等操作参数。 协议驱动程序可以查询或设置基础驱动程序的操作参数。 NDIS 还为 NDIS 6.1 及更高版本的协议驱动程序提供直接 OID 请求接口。 直接 OID 请求路径支…

5-时间、日期与组合框

时间、日期与组合框 1 日期时间1.1 日期时间相关的类1.2 日期、时间和字符串的转换1.3 例子 2、组合框2.1 QComboBox2.2 QPlainTextEdit2.3 案例 3、自定义右键菜单 1 日期时间 1.1 日期时间相关的类 QTime 时间数据类型&#xff0c;仅表示时间&#xff0c;如&#xff1a;15:…

nano机器人2:机械臂的视觉抓取

前言 参考链接: 【机械臂入门教程】机械臂视觉抓取从理论到实战 GRCNN 通过神经网络&#xff0c;先进行模型训练&#xff0c;在进行模型评估。 机械臂逆运动学求解 所有串联型6自由度机械臂均是可解的&#xff0c;但这种解通常只能通过数值解法得到&#xff0c;计算难度大&am…

Python | Leetcode Python题解之第118题杨辉三角

题目&#xff1a; 题解&#xff1a; class Solution:def generate(self, numRows: int) -> List[List[int]]:ret list()for i in range(numRows):row list()for j in range(0, i 1):if j 0 or j i:row.append(1)else:row.append(ret[i - 1][j] ret[i - 1][j - 1])ret…

如何批量提取pdf文件名?批量提取文件夹里的文件名,只要用对方法!

在数字化时代&#xff0c;PDF文件已经成为我们日常工作中不可或缺的一部分。然而&#xff0c;随着PDF文件数量的不断增加&#xff0c;如何高效地管理这些文件成为了一个挑战。批量提取PDF文件名&#xff0c;就是解决这一问题的关键所在。本文将为你介绍几种实用的方法&#xff…