问题描述与解题思路
确定本题的状态表示
dp[i]可以表示为第i天结束之后我手里的最大利润,但是这样表示,我问题也不好处理,因为你第i天有很多状态,我们主要从你第i天手里有没有股票来进行分析
- 如果你手里有一张股票,那么今天你的操作就只有两种,第一种就是把手里的这只股票卖了,第二种就是依旧保持手里的股票
- 如果你手里没股票,那么你今天的操作也只有两种,第一种是买入股票,第二种是依然不买入。
当然股票也不是你想买就能买的,今天你没买股票不一定是你不想买。可能这一天你处于冷冻期,没有办法进行任何操作。也有可能你这一天虽然不处于冷冻期,但是手里已经持有一个股票了,无法再买入股票。还有可能你这一天能买股票(我们称之为处于可交易的状态),但是你没有买股票
因此我们需要根据对第i天的状态对dp[i]进行细化:
首先定义买股票时一天可能处于的三个状态:
dp[i][0] 表示:第 i 天结束之后,处于“买入”状态,此时的最大利润
dp[i][1] 表示:第 i 天结束之后,处于“可交易”状态,此时的最大利润
dp[i][2] 表示:第 i 天结束之后,处于“冷冻期”状态,此时的最大利润
确定本题的状态转移方程
然后我们就要明确上面我们定义的几种状态是啥意思,以及这几种状态能不能在相邻两天相互转化。
买入状态的意思就是你手里持有着一张股票。冷冻期状态的意思就是此时你手里没有股票,但是不允许进行买入。可交易的状态指的是你手里没有股票,但是允许你在今天进行买入。
下面我们先来分析买入状态能不能在第二天保持或者转化成其他的状态。
买入状态的意思就是你手里持有着一张股票。如果你昨天手里持有一张股票,那么今天啥也不干。今天结束的时候,你手里依然可以持有一张。因此买入状态是可以保持下去的。如果你昨天手里持有一张股票,今天把这张股票卖出去了。那么在今天结束的时候,你就会进入冷冻期的状态,也就是说明天你不能进行买入操作。由于买入状态你手里是有票的,而可交易的状态你手里是没票的,所以你想从买入状态转换到可交易状态,就必须要把票卖掉,但是把票卖掉之后,系统规定必须先要进入冷冻期的状态,所以买入状态第二天并不能直接转化到可交易状态
然后我们再来分析冷冻期状态能不能在第二天保持或者转化成其他的状态。首先根据定义它肯定不能保持。然后他第二天一定是会转化成交易的状态。这个感觉没啥好说的。
最后就是来分析可交易状态能不能在第二天保持或者转化成其他的状态。首先如果我啥也不干,并不在当天进行买入,那我第二天依然是处于可交易状态,所以说它可以保持。其次就是如果我前一天处于可交易状态,然后买入了股票。那么在第二天结束的时候,我就可以处于买入的状态。然后根据定义只能由冷冻期到可交易,不能由可交易到冷冻期。
理清关系之后,我们就可以画出下面的关系图(有点像进程的几个状态之间转换的那个图)

理清关系图之后,下面我们就可以直接来写状态转移方程了。
先来看一下第i天结束时处于买入状态的最大利润dp[i][0]。首先第i天处于买入状态说明第二天结束的时候,你手里是持有股票的。那么这个股票它有可能是今天刚买的。也有可能是之前买然后保留下来的,如果是今天刚买的,那么今天的最大利润就是dp[i-1][1]-price[i],如果不是今天买的,那么今天的最大利润就是dp[i-1][0],综合考虑两种情况,我们要求最大值,所以
dp[i][0]=max(dp[i-1][0],dp[i-1][1]-price[i])
然后我们再看一下第i天结束时处于可交易状态的最大利润dp[i][1],根据我们上面的关系图,当且仅当第i-1天处于冷冻期状态或者可交易状态,第i天才可能处于可交易状态。但是无论是上面哪种情况,第i天都不会进行股票的买入和卖出,因此
dp[i][1]=max(dp[i-1][1],dp[i-1][2])
最后我们再来看一下第i天结束处于冷冻期状态的最大利润dp[i][2],根据上面的关系图,当且仅当第i-1天处于买入状态,并且在第i天当天将手里的股票卖出,第i天结束的时候处于冷冻期状态,因此
dp[i][2]=dp[i-1][0]+prices[i]
初始值确定
在进行动态规划之前我们还要确定:dp[1][0],dp[1][1]和dp[1][2]的值,在股票开盘之前,我们手里并没有股票,因此第一天我们只能够进行买入的操作,如果进行买入,那么第一天结束的时候我们就处于买入的状态。利润dp[1][0]=0-prices[0],如果不进行买入,那么第一天结束的时候,我们就处于可交易的状态,此时利润dp[1][1]依然是零。由于第一天结束的时候不可能处于冷冻期状态,dp[1][0]我们也定义为零
代码实现
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n=prices.size();
vector<vector<int>> dp(n+1,vector<int>(3,0));
dp[1][0]=-prices[0];dp[1][1]=0;dp[1][2]=0;
for(int i=2;i<=n;i++){
dp[i][0]=max(dp[i-1][0],dp[i-1][1]-prices[i-1]);
dp[i][1]=max(dp[i-1][2],dp[i-1][1]);
dp[i][2]=dp[i-1][0]+prices[i-1];
}
return max({dp[n][0],dp[n][1],dp[n][2]});
}
};

738

被折叠的 条评论
为什么被折叠?



