首页 > 其他分享 >动态规划(4)——简单多状态Ⅱ

动态规划(4)——简单多状态Ⅱ

时间:2024-10-14 20:17:10浏览次数:8  
标签:int max vector 简单 prices 股票 动态 规划 dp

题一.买卖股票的最佳时机含冷静期

题目描述

给定一个整数数组prices,其中第  prices[i] 表示第 i 天的股票价格 。​

设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

  • 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:

输入: prices = [1,2,3,0,2]
输出: 3
解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]

示例 2:

输入: prices = [1]
输出: 0

题目分析

dp[i][0]表示,第i天处于手里有股票状态所能达到的最大利润
dp[i][1]表示,第i天处于可以进行交易的状态所能达到的最大利润
dp[i][2]表示,第i天处于刚卖完股票的状态所能达到的最大利润

题解

class Solution {
public:
	int maxProfit(vector<int>& prices)
	{
		int n = prices.size();
		vector<vector<int>> dp(n, vector<int>(3,0));
		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(dp[n - 1][1], dp[n - 1][2]);
	}
};

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

题目描述

给定一个整数数组 prices,其中 prices[i]表示第 i 天的股票价格 ;整数 fee 代表了交易股票的手续费用。

你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。

返回获得利润的最大值。

注意:这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。

示例 1:

输入:prices = [1, 3, 2, 8, 4, 9], fee = 2
输出:8
解释:能够达到的最大利润: 
在此处买入 prices[0] = 1
在此处卖出 prices[3] = 8
在此处买入 prices[4] = 4
在此处卖出 prices[5] = 9
总利润: ((8 - 1) - 2) + ((9 - 4) - 2) = 8

示例 2:

输入:prices = [1,3,7,5,10,3], fee = 3
输出:6

题目分析

dp[i][0]表示:第i天选择卖股票的利润最大值
dp[i][1]表示:第i天选择买入股票的利润的最大值

题解

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] = 0, dp[0][1] = -prices[0];
		for (int i = 1; i < n; ++i)
		{
			dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i] - fee);
			dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
		}
		return dp[n - 1][0];
	}
};

题三.买卖股票的最佳时机Ⅲ 

题目描述

给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:

输入:prices = [3,3,5,0,0,3,1,4]
输出:6
解释:在第 4 天(股票价格 = 0)的时候买入,在第 6 天(股票价格 = 3)的时候卖出,这笔交易所能获得利润 = 3-0 = 3 。
     随后,在第 7 天(股票价格 = 1)的时候买入,在第 8 天 (股票价格 = 4)的时候卖出,这笔交易所能获得利润 = 4-1 = 3 。

示例 2:

输入:prices = [1,2,3,4,5]
输出:4
解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。  
     注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。  
     因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。

示例 3:

输入:prices = [7,6,4,3,1]
输出:0
解释:在这个情况下, 没有交易完成, 所以最大利润为 0。

示例 4:

输入:prices = [1]
输出:0

题目分析

dp[i]表示:第i天结束之后,所能获得的最大利润
f[i][j]表示:第i天结束之后,完成了j次交易,此时处于“买入”状态下的 最大利润
g[i][j]表示:第i天结束之后,完成了j次交易,此时处于“卖出”状态下的 最大利润

f[i][j]=max(f[i-1][j],g[i-1][j]-prices[i])
g[i][j]=max(g[i-1][j],f[i-1][j-1]+prices[i])
避免讨论g[i][j]的取值边界,可以采用条件判断减少麻烦

 题解

class Solution {
public:
	const int INF = 0x3f3f3f;
	int maxProfit(vector<int>& prices)
	{
		int n = prices.size();
		//用±0x3f3f3f(±无穷小的一半)
		vector<vector<int>> f(n, vector<int>(3, -INF));
		auto g = f;
		g[0][0] = 0,f[0][0] = -prices[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 j = 0; j < 3; j++)
			ret = max(ret, g[n - 1][j]);
		return ret;
	}
};

题四.买卖股票的最佳时Ⅳ

题目描述

给你一个整数数组 prices 和一个整数 k ,其中 prices[i] 是某支给定的股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。也就是说,你最多可以买 k 次,卖 k 次。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

题解

class Solution {
public:
	const int INF = 0x3f3f3f;
	int maxProfit(int k, vector<int>& prices)
	{
		int n = prices.size();
		k = min(k, n / 2);
		vector<vector<int>> f(n, vector<int>(k + 1, -INF));
		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 + 1; 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 = g[n - 1][0];
		for (int j = 1; j < k + 1; j++)
			ret = max(ret, g[n - 1][j]);
		return ret;
	}
};

标签:int,max,vector,简单,prices,股票,动态,规划,dp
From: https://blog.csdn.net/weixin_74042627/article/details/142920667

相关文章

  • (nice!!!)(LeetCode) 1884. 鸡蛋掉落-两枚鸡蛋(动态规划 dfs递归和递推 || 数学)
    题目:1884.鸡蛋掉落-两枚鸡蛋方法一:动态规划dp+递归dfs+记忆化搜索。时间复杂度0(n^2)。C++版本:classSolution{public: //状态sta[i]表示:i层找到f所需要的最小操作次数intsta[1010];inttwoEggDrop(intn){ //层数为0时,直接返回0if(n==0......
  • 了解 java web并写一个简单的登录功能
    首先我们要知道什么是servlet,它允许开发者创建动态Web内容。Servlet是Java编写的服务器端程序,它扩展了Java的功能,使得它可以在客户端请求时产生动态内容,并且可以与数据库交互。在Java中实现servlet有三种方式:继承HttpServlet抽象类,实现Servlet接口,继承GenericServlet抽......
  • 倾斜摄影切片怎么做?这种切片方式简单方便还免费!
    倾斜摄影是一种从多个角度(通常是垂直、斜45度)拍摄地面或建筑物的影像技术,通过结合这些不同视角的照片,可以生成具有真实感的三维模型。倾斜摄影通常用于城市建模、地形勘测和测绘等领域,能够准确还原建筑物和地形的立体结构。然而,倾斜摄影生成的三维数据体量庞大,直接展示时面临渲染......
  • Squid代理服务器搭建和简单使用
    1Squid的介绍1.1前言简介代理服务器(ProxyServer)的功能是代理网络用户去取得网络信息。形象地说,它是网络信息的中转站,是个人网络和Internet服务商之间的中间代理机构,负责转发合法的网络信息,对转发进行控制和登记。[1]代理服务器作为连接Internet与Intranet的桥梁,在实际应用......
  • VMware NSX-T网络虚拟化规划设计
    1.硬件资源介绍采用4台服务服务器和1台千兆二层交换机,路由器采用虚拟化VYOS模拟在管理集群中部署vcenter+DNS+vyos+nsx-t-manager+edge+harbor工作节点A跑业务虚拟机和测试虚拟机工作节点B跑tanzu和NSXApplicationPlatform序号机器数量备注1Cisco2960124......
  • DIY Matter Bridge 和智能锁简单联动的实践
    一.写在前面在之前的博客文章《基于乐鑫ESP32-C3的MatterLight实践》中,我们利用乐鑫的硬件和SDK方案实现了简单的Light例程,并对Matter协议进行了简要介绍。在开始本篇文章之前,我还是打算重新聊一聊Matter,顺便谈谈自己对它的理解,这也能说明为何这段时间我一直执着于......
  • 2024年入职_转行网络安全,该如何规划?_网络安全职业规划
    前言前段时间,知名机构麦可思研究院发布了《2023年中国本科生就业报告》,其中详细列出近五年的本科绿牌专业,其中,信息安全位列第一。网络安全前景对于网络安全的发展与就业前景,想必无需我多言,作为当下应届生收入较高的专业之一,网络安全同样也在转行领域中占据热门位置,主要......
  • 媲美ps却比ps操作简单--Luminar Neo macOS照片编辑激活版
    LuminarNeo是一款由Skylum公司开发的先进照片编辑软件,融合了人工智能技术,旨在为摄影师和图像处理爱好者提供创新、简便的编辑体验。它支持Windows和macOS系统,具备AI驱动的编辑工具,能够轻松完成从基础调整到复杂修饰的各种任务。同时,其模块化的界面和灵活的工作流程,使用户能够根......
  • 通信工程学习:什么是SDRAM同步动态随机存取存储器
    SDRAM:同步动态随机存取存储器    SDRAM,全称为SynchronousDynamicRandomAccessMemory,即同步动态随机存取存储器,是一种广泛应用于计算机和嵌入式系统中的内存技术。以下是对SDRAM的详细介绍:一、SDRAM的定义与特点        SDRAM的定义:   SDRAM是一......
  • Java语言中1.方法调用栈 2.栈帧 3.局部变量表 4.操作数栈 5.动态链接 6.方法的入参存
    在Java语言中,理解方法调用栈、栈帧、局部变量表、操作数栈等概念非常重要,它们与方法的执行和内存管理密切相关。下面是对这些概念的详细解释及它们之间的关系:1.方法调用栈(MethodCallStack)方法调用栈是每个线程维护的一块内存区域,用于存储线程执行时的栈帧(每个栈帧对应一次......