当前位置:   article > 正文

【动态规划--买卖股票的最佳时期系列2】_动态规划股票买卖2例子推倒

动态规划股票买卖2例子推倒

力扣题目链接
给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。
设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
实例

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

动态规划5步曲

  • 确定dp数组以及下标的含义
    dp[i][j],第i天状态为j,所剩的最多现金为dp[i][j]。
    本题的状态相对于系列一复杂了不少。具体分了如下四个状态:
 - 状态一:买入股票状态(今天买入股票,或者是之前就买入了股票然后没有操作)
 
    卖出股票状态,这里就有两种卖出股票状态
    
 - 状态二:两天前就卖出了股票,度过了冷冻期,一直没操作,今天保持卖出股票状态
 - 状态三:今天卖出了股票

 - 状态四:今天为冷冻期状态,但冷冻期状态不可持续,只有一天!

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

注意这里的每一个状态,例如状态一,是买入股票状态并不是说今天已经就买入股票,而是说保存买入股票的状态即:可能是前几天买入的,之后一直没操作,所以保持买入股票的状态。

j的状态为:
0:状态一;1:状态二;2:状态三;3:状态四
  • 1
  • 2

确定递推式
达到买入股票状态(状态一)即:dp[i][0],有两个具体操作:

操作一:前一天就是持有股票状态(状态一),dp[i][0] = dp[i - 1][0]
操作二:今天买入了,有两种情况
前一天是冷冻期(状态四),dp[i - 1][3] - prices[i]
前一天是保持卖出股票状态(状态二),dp[i - 1][1] - prices[i]
所以操作二取最大值,即:max(dp[i - 1][3], dp[i - 1][1]) - prices[i]
那么dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][3], dp[i - 1][1]) - prices[i]);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

达到保持卖出股票状态(状态二)即:dp[i][1],有两个具体操作:

操作一:前一天就是状态二
操作二:前一天是冷冻期(状态四)
dp[i][1] = max(dp[i - 1][1], dp[i - 1][3]);
  • 1
  • 2
  • 3

达到今天就卖出股票状态(状态三),即:dp[i][2] ,只有一个操作:

操作一:昨天一定是买入股票状态(状态一),今天卖出
即:dp[i][2] = dp[i - 1][0] + prices[i];
  • 1
  • 2

达到冷冻期状态(状态四),即:dp[i][3],只有一个操作:

操作一:昨天卖出了股票(状态三)
dp[i][3] = dp[i - 1][2];
  • 1
  • 2

综上分析得递推公式:

dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][3], dp[i - 1][1]) - prices[i]);
dp[i][1] = max(dp[i - 1][1], dp[i - 1][3]);
dp[i][2] = dp[i - 1][0] + prices[i];
dp[i][3] = dp[i - 1][2];

  • 1
  • 2
  • 3
  • 4
  • 5

dp数组如何初始化
这里主要讨论一下第0天如何初始化。
如果是持有股票状态(状态一)那么:dp[0][0] = -prices[0],买入股票所剩现金为负数。
保持卖出股票状态(状态二),第0天没有卖出dp[0][1]初始化为0就行。
今天卖出了股票(状态三),同样dp[0][2]初始化为0,因为最少收益就是0,绝不会是负数。
同理dp[0][3]也初始为0。
确定遍历顺序
从递归公式上可以看出,dp[i] 依赖于 dp[i-1],所以是从前向后遍历。
举例推导dp数组
以 [1,2,3,0,2] 为例,dp数组如下:
在这里插入图片描述
最后结果是取 状态二,状态三,和状态四的最大值。
代码如下:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class Solution{
	public:
		int maxProfit(vector<int> &prices) {
			int n = prices.size();
			if (n == 0) return 0;
			vector<vector<int>> dp(n,vector<int>(4,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][3]-prices[i]});
                //买入股票状态
				dp[i][1] = max(dp[i-1][1],dp[i-1][3]);
                //两天前就卖出股票,度过了冷冻期,一直没有操作,今天保持卖出股票的状态
				dp[i][2] = dp[i-1][0] + prices[i];
                //今天卖出了股票
				dp[i][3] = dp[i-1][2];
                //今天为冷冻期,但冷冻期状态不可持续,只有一天
			}
			return max({dp[n-1][3],dp[n-1][2],dp[n-1][1]});
		}
}; 
int main() {
	Solution Q;
	int n;
	cin>>n;
	vector<int> price(n);
	for (int i = 0; i < n; i++) {
		cin>>price[i];
	}
	cout<<Q.maxProfit(price);
} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/628930
推荐阅读
相关标签
  

闽ICP备14008679号