股票问题dp
1状态设定
定义dp[i][k][j]为第i天(从0~n-1),当前最多买入k次,j为0或1,表示当前是否持有股票。
2 递推关系
dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1] + prices[i])
max( 选择 rest , 选择 sell )
解释:今天我没有持有股票,有两种可能:
要么是我昨天就没有持有,然后今天选择 rest,所以我今天还是没有持有;
要么是我昨天持有股票,但是今天我 sell 了,所以我今天没有持有股票了。
dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0] - prices[i])
max( 选择 rest , 选择 buy )
解释:今天我持有着股票,有两种可能:
要么我昨天就持有着股票,然后今天选择 rest,所以我今天还持有着股票;
要么我昨天本没有持有,但今天我选择 buy,所以今天我就持有股票了。
作者:labuladong
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iii/solution/yi-ge-tong-yong-fang-fa-tuan-mie-6-dao-gu-piao-wen/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
3 k的遍历顺序
如果k的定义是,当前最多买入k次,那么就从1~kmax;
如果k的定义是,当前还可以最多买k次,那么就从kmax~1;
4 basecase如何设计
当i==-1时,很容易有
dp[-1][任意的k][0]=0;//不论什么时候,当前还没开始,即使最多买k次,那么没有持有,最大利润就是0;
dp[-1][任意的k][1]=-inf;//不论什么时候,当前还没开始,最多买k次,当前已经持有,这是不可能的,因此定义为负无穷。
我们根据basecase,要设定的是i == 0的情况,所以我们必须对i==0的情况,带入到2里面去,最终得到如下代码!
代码
class Solution {
public:
const int MinInf=INT_MIN;
int maxProfit(vector<int>& prices) {
int kmax=2;
int n=prices.size();
if(n==0)return 0;
vector<vector<vector<int>>> dp(n,vector<vector<int>>(kmax+1,vector<int>(2,0)));
for(int i=0;i<n;i++){
for(int k=1;k<=kmax;k++){
if(i==0){
dp[i][k][0]=0;
dp[i][k][1]=-prices[i];
continue;
}
dp[i][k][0]=max(dp[i-1][k][0],dp[i-1][k][1]+prices[i]);
dp[i][k][1]=max(dp[i-1][k][1],dp[i-1][k-1][0]-prices[i]);
}
}
return dp[n-1][kmax][0];
}
};