目录
一:股票类通用框架介绍
一:前言
股票买卖问题是有共性的,我们先对第四题(限制最大交易次数为k)的分析一道一道解决。
因为第四题(限制最大交易次数为k)是最泛化的形式,其它问题都是这个形式的简化。
第一题:只进行一次交易,相当于k = 1;
第二题:不限交易次数,相当于k = 正无穷
第三题:只进行2次交易,相当于k = 2;
第五题和第六题:不限次数,增加六交易冷冻期和手续费的额外条件。
二:穷举框架
对于股票问题,我们不用递归思想进行穷举,而是利用状态进行穷举。
我们具体到每一天,看总共有几种可能的状态,再找出每个状态对应的选择。
我们穷举所有的状态,穷举的目的是根据对应的选择更新状态。
框架代码流程图:
for 状态1 in 状态1的所有取值:
for 状态2 in 状态2的所有取值:
for ...
dp[状态1][状态2][...] = 择优(选择1,选择2,...)
股票问题,每天都有三种选择:买入,卖出,无操作,我们用buy,sell, rest表示这三种选择。
但问题是,并不是每天都可以任意选择这三种选择的,因为sell必须在buy之后,buy必须在sell之后。
那么rest操作还应该分两种状态,一种是buy之后的rest(持有股票),一种是sell之后的rest(此时没有持有股票)。
注意,我们还有交易次数k的限制。就是说你buy还只能在k >0 的前提下操作。
上面这么多都是为了进行穷举。股票问题的变量有三个:第一个是天数,第二个是允许交易的最大次数,
第三个是当前的持有状态(一般1表示持有,0表示没有持有)。我们使用一个三维数组装下这几种状态的全部组合。
dp[i][k][0 or 1]
0 <= i <= n-1, 1 <= k <= K
n为天数,K为最多交易数
此问题共n * K * 2种状态,全部穷举就能够搞定
for 0 <= i <= n:
for 1 <= k <= K:
for s in {0,1}:
dp[i][k][s] = max{buy , sell , rest}
我们最后想求的答案是dp[n-1][K][0],即最后一天,最多允许k次交易,最多获得多少利润。
三:状态转移框架
上面完成了状态的穷举,我们思考每种状态有哪些选择,应该如何更新状态,只看持有状态,
画出状态转移图。
通过状态转移图,我们可以很清楚看到,每种状态(0和1)是如何转移而来的,
依据这个图,我们来写一下状态转移方程1
dp[i][k][0] = max(dp[i-1][k][0] , dp[i-1][k][1] + price[i])
即 max(选择rest, 选择sell)
状态转移方程解释: 今天我没有持有股票,有两种原因:
1)昨天就没有持有,今天选择rest,所以今天还是没有持有;
2)昨天持有股票,但是sell了,所以今天没有持有股票。
状态转移方程2:
dp[i][k][1] = max(dp[i-1][k][1] , dp[i-1][k-1][0] - price[i])
即 max(选择rest , 选择buy)
状态转移方程解释:
今天我持有股票,有两种可能:
1)要么我昨天就持有股票,然后今天选择rest;
2)要么昨天本就没有持有股票,但是今天选择buy。
四.注意事项
利润变化和k值改动
如果buy,就要从利润中减去price[i],如果sell,就要给利润增加prices[i].
今天的最大利润就是这两种可能选择较大的那个。而且注意k的限制,
我们在选择buy的时候,把k减少了1,因此sell的时候对k就不需要再次改动了。