解体思路
-
约束条件很多
- 卖出股票只能在买入股票之后。
- 卖出股票后需要等一天内才能继续买入股票。
- 如果把卖出当作两天,需要对最后一天的卖出进行特殊的操作,这十分的麻烦。
-
解决这种复杂的问题一般采用动态规划(经验所致),状态确定了转移方程都不难,难的是确定状态。
- 如何确定状态?
- d p [ i ] [ j ] dp[i][j] dp[i][j]代表啊第一次买入在第 i i i天,最后一次卖出在第 j j j天可不可以?产生问题:卖出股票后需要等一天才能继续买入怎么考虑进?如何糅合入 p r i c e s [ i ] prices[i] prices[i]这个东西?这种状态不好。
- 于是我们考虑,既然约束条件十分的复杂,为什么我们不把约束条件放到我们的状态中?
-
考虑将约束条件糅合进我们的状态中:
-
什么状态?
-
d p [ i ] dp[i] dp[i]代表第 i i i天结束后我们手头的最大的收入?
-
第 i i i天结束后我们有好几种状态?怎么考虑到这个的?因为这个卖出后还要等一天的设定,造成了很多的状态,这个是在是太麻烦了,所以我们把它拆分出来考虑。
-
那么有:
-
d p [ i ] [ 0 ] dp[i][0] dp[i][0]代表第 i i i天结束后我们手头有股票的最大收入。
-
d p [ i ] [ 1 ] dp[i][1] dp[i][1]代表第 i i i天结束后我们手头没有股票且处于冻结期的最大收入。
-
d p [ i ] [ 2 ] dp[i][2] dp[i][2]代表第 i i i天结束后我们手头没有股票且不处于冻结期的最大收入。
-
有了这个状态,我们的状态转移实在是太简单了!有一个需要注意的是,我们的状态的规定是一个累计的东西,我们得到第 i i i天的东西只需要从第 i − 1 i-1 i−1天去得到,不需要考虑前面的 i − 2 , i − 3 , . . . i-2,i-3,... i−2,i−3,...等等的东西,因为第 i i i天的状态可以从第 i − 1 i-1 i−1天丝滑的过度过来。
-
那么写下状态转移方程:
d p [ i ] [ 0 ] = m a x ( d p [ i − 1 ] [ 2 ] − p r i c e s [ i ] , d p [ i − 1 ] [ 0 ] ) dp[i][0]=max(dp[i-1][2]-prices[i],dp[i-1][0]) dp[i][0]=max(dp[i−1][2]−prices[i],dp[i−1][0])
d p [ i ] [ 1 ] = d p [ i − 1 ] [ 0 ] + p r i c e s [ i ] dp[i][1]=dp[i-1][0]+prices[i] dp[i][1]=dp[i−1][0]+prices[i]
d p [ i ] [ 2 ] = m a x ( d p [ i − 1 ] [ 1 ] , d p [ i − 1 ] [ 2 ] ) dp[i][2]=max(dp[i-1][1],dp[i-1][2]) dp[i][2]=max(dp[i−1][1],dp[i−1][2])
-
初始状态三个:
d p [ 0 ] [ 2 ] = 0 ; 第 一 天 结 束 后 不 持 有 股 票 且 处 于 非 冷 冻 期 dp[0][2]=0; 第一天结束后不持有股票且处于非冷冻期 dp[0][2]=0;第一天结束后不持有股票且处于非冷冻期
d p [ 0 ] [ 0 ] = − p r i c e s [ 0 ] ; 第 一 天 结 束 后 持 有 股 票 dp[0][0]=-prices[0]; 第一天结束后持有股票 dp[0][0]=−prices[0];第一天结束后持有股票
d p [ 0 ] [ 1 ] = 0 ; 第 一 天 结 束 后 不 持 有 有 股 票 且 处 于 冷 冻 期 dp[0][1]=0; 第一天结束后不持有有股票且处于冷冻期 dp[0][1]=0;第一天结束后不持有有股票且处于冷冻期
-
class Solution {
public:
int dp[10005][3];
int maxProfit(vector<int>& prices) {
int n=prices.size();
/*
* 这句话需要些,被坑一次
*/
if(n==0){
return 0;
}
dp[0][2]=0; // 第一天结束后不持有股票且处于非冷冻期
dp[0][0]=-prices[0]; // 第一天结束后持有股票
dp[0][1]=0; // 第一天结束后不持有有股票且处于冷冻期
for(int i=1;i<n;i++){
// 第i天结束后持有股票,可能
// 1. 由第i-1天结束后持有股票转化
// 2. 由低i-1天结束后不持有股票但是第i天购买了股票转化而来
dp[i][0]=max(dp[i-1][2]-prices[i],dp[i-1][0]);
// 第i天结束后不持有股票,处于冷冻期
// 1. 第i-1天结束后持有股票,第i天卖掉了股票转化而来
dp[i][1]=dp[i-1][0]+prices[i];
// 第i天结束后不持有股票,不处于冷冻期
// 1. 第i-1天结束后不持有股票,处于冷冻期转化而来
// 2. 第i-1天结束后不持有股票,不处于冷冻期转化而来
dp[i][2]=max(dp[i-1][1],dp[i-1][2]);
}
int res=max(dp[n-1][1],dp[n-1][2]);
printf("%d\n",res);
return res;
}
};