动态规划之多状态问题(股票买卖利润最大)

题目分析 

股票买入后不能在买,也就是必须买入后卖出才能买

一次交易叫买卖,这样的交易次数不能超过两次

返回最大利润

算法原理

状态表示:

经验+题目要求

经验:以i位置为结尾,巴拉巴拉

题目要求:以i位置为结尾,所能获得的最大利润

细分状态:由于通过题目可以得出,i天结束后可能处于买入状态或者卖出状态(买入就是i天结束后手里有股票,卖出就是i天结束后手里没股票)

此时又发现,题目要求最多只能交易两次,也就是你能交易0/1/2次

所以状态又可以细分,i天结束后,处于买入状态,此时交易了0次 

                                   i天结束后,处于买入状态,此时交易了1次

等等6种情况

那我们可以简化一下,创建两个dp表,一个f,一个g

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

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

分析:f[i][j]=什么???

第i天结束时是买入状态:可以由第i-1天结束时买入状态(手里有股票)我不卖股票,此时就会i天结束后处于买入状态+由卖出(手里没股票)到买入(手里有股票)

第i天结束时是卖出状态:可以由i-1天结束时卖出状态(手里没股票),我不买股票,此时i天结束时就会处于卖出状态+由买到卖出(把手里股票卖了)

注意:我们这里处理交易次数是以卖出时才增加,你当然也可以买入的时候就增加

f[i][j]=max(f[i-1][j],g[i-1][j]-p[i]);

注意这里第i-1天的j是跟第i天的j一样的,因为你买入到买入,你的交易次数都没变,卖出也一样

g[i][j]=max(g[i-1][j],f[i-1][j-1]+p[i])

注意:卖出到卖出,交易次数肯定没变,但买入到卖出交易次数就变了,如果你i天交易次数是2,那么i-1天交易次数肯定是1,所以f那里的交易次数是j-1

初始化:

f[i][j]=max(f[i-1][j],g[i-1][j]-p[i]);

g[i][j]=max(g[i-1][j],f[i-1][j-1]+p[i])

这里发现你在算f的时候会用到i-1,所以需要我们初始化第一行,然后从第二行开始填表

这里发现你再算g的时候会用到i-1和j-1,所以我们需要初始化第一行和第一列,但这样过于麻烦,

也就是用填第一列时需要用到负一列的值,就是你今天是结束时是卖出状态,且交易次数为0,那你昨天交易次数肯定不能是-1吧,所以你可以这样处理先去g[i-1][j]的值

如果j-1>=0,亦或者你的j>=1,也就是你今天结束后处于卖出状态时你的交易次数至少为1;

 

f[0][0]的位置肯定设成-prices[0]代表你第1天结束后买了股票时的最大利润

而且此时你交易次数是0,因为我们上面处理了当你买了之后在卖交易次数才会+1

g[0][0]:填0,啥都不干

其他位置的填写不能影响下面的填表 :

第一天完成一笔交易和第一天完成两笔交易的情况根本就不存在

所以我们求max的时候就不要让f[0][1]和f[0][2]的位置的值干扰后面的结果,所以让他们的位置是负无穷就好,但有些编译器在处理时负无穷减去一个数字可能会得到一个正数,所以负无穷那里我们可以初始化成-0x3f3f3f3f(这个数字是int的一半)

 

为什么不是f表,你想想如果你手里有股票和手里没股票哪个的利润大

代码编写

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值