第80题 股票价格预测
小R近期表现出色,公司决定以股票的形式给予奖励,并允许他在市场上进行交易以最大化收益。给定一个数组,数组中的第
i个元素代表第i天的股票价格。小R需要设计一个算法来实现最大利润。
股票交易规则如下:
- 小R可以多次买卖股票,但在买入新的股票前必须卖出之前的股票。
- 每次卖出股票后存在一天的冷冻期,在冷冻期内小R不能购买股票。
题目解读
关键是这个规则,每一天有三种状态 所以我们考虑用动态规划思路来解决此问题
定义若干状态变量来追踪每天不同情况下的收益:
-
状态定义:
dp[i][0]:第i天 不持有股票 的最大收益(可以是冷冻期或之前已经卖出)。dp[i][1]:第i天 持有股票 的最大收益。dp[i][2]:第i天处于 冷冻期 的最大收益(当天卖出了股票)。
-
状态转移公式:
-
dp[i][0]:-
第
i天不持有股票的两种情况:- 昨天不持有股票,今天继续保持不持有状态:
dp[i-1][0] - 今天处于冷冻期结束后,不再持有股票:
dp[i-1][2]
- 昨天不持有股票,今天继续保持不持有状态:
-
转移公式:
dp[i][0] = max(dp[i-1][0], dp[i-1][2] - stocks[i])
-
-
dp[i][1]:-
第
i天持有股票的两种情况:- 昨天就持有股票,今天继续持有:
dp[i-1][1] - 今天买入股票(只能在昨天没有股票的情况下买入):
dp[i-1][0] - stocks[i]
- 昨天就持有股票,今天继续持有:
-
转移公式:
dp[i][1] = dp[i-1][0] + stocks[i]
-
-
dp[i][2]:-
第
i天处于冷冻期的情况:- 今天刚卖出股票:
dp[i-1][1] + stocks[i]
- 今天刚卖出股票:
-
转移公式:
dp[i][2] = max(dp[i-1][2], dp[i-1][1])
-
-
-
初始化(即为第 0 天的状态):
dp[0][0] = 0:不持有股票,收益为 0。dp[0][1] = -stocks[0]:持有股票,收益为负的买入价格。dp[0][2] = 0:冷冻期收益为 0。
结果
最后一天的最大收益是 dp[n-1][0] 或 dp[n-1][2],因为最后一天不可能持有股票。
所以只需要retrun max(dp[i][1], dp[i][2])
一些思考
dp动态规划是近年来CSP等算法比赛非常热门的题目,而笔者认为这是最容易AC混分的一类题型.怎么知道要用dp呢,看到不容易算出n的最优解时,就可以考虑用dp了,因为这个算法的实质是维护前后几个状态(也即是状态转移方程),求出递推公式就易如反掌了.
- 记住以下步骤,秒杀dp
- 定义dp (理解dp[i][j] 中每个变量非常重要, 这样递推公式才不会混乱)
- 状态转移方程
- 初始化dp 状态为0