题目中要求最多可以完成k次交易,很多时候不要把问题搞复杂了,
按照题目要求,研究对象是最后一天结束后最多进行了 k 次交易获得的最大利润
那么就可以把问题拆分成
第 1 天结束后完成 0 次交易获得的最大利润,第 1 天结束后完成 1 次交易获得的最大利润,
第 1 天结束后完成 k 次交易获得的最大利润,
第 2 天结束后完成 0 次交易获得的最大利润,第 2 天结束后完成 1 次交易获得的最大利润,
第 2 天结束后完成 k 次交易获得的最大利润,
第 i 天结束后完成 0 次交易获得的最大利润,第 i 天结束后完成 1 次交易获得的最大利润,
第 i 天结束后完成 k 次交易获得的最大利润,
由于规则中强调不能同时参与多笔交易,所以前一天是否持有股票会影响第二天
值得注意的是,需要针对前一天已经处于未持有股票的状态进行特殊分析
已知到了第 i 天的开始,已经完成了 j 次交易,且第 i 天可以买入股票,
那么第 i 天可以做的决策就是:买入股票,或者静观其变
此时买入股票确实会影响之后的递归,但即使买入股票,也不构成新的交易
可以将状态表示定义为:
f[i][j]: 第 i 天结束后,完成了 j 次交易,处于持有股票的状态所获得的最大利润
g[i][j]: 第 i 天结束后,完成了 j 次交易,处于未持有股票的状态所获得的最大利润
状态转移方程:
g[i][j] = g[i - 1][j];
f[i][j] = max(f[i - 1][j], g[i - 1][j] - prices[i][j]);
if(j - 1 >= 0){
g[i][j] = max(g[i - 1][j], f[i - 1][j - 1] + prices[i][j]);
}
class Solution {
public:
int maxProfit(int k, vector<int>& prices) {
int n = prices.size();
vector<vector<int>> f(n, vector<int>(k + 1, -1 * 0x3fffff));
vector<vector<int>> g(n, vector<int>(k + 1, -1 * 0x3fffff));
// 此题可以不做dp初始化扩容,只需要因为第一天的处于两种状态的情况的最大利润已知
f[0][0] = -1 * prices[0];
g[0][0] = 0;
for (int i = 1; i < n; i++){
for (int j = 0; j < k + 1; j++){
g[i][j] = g[i - 1][j];
f[i][j] = max(f[i - 1][j], g[i - 1][j] - prices[i]);
if(j - 1 >= 0){
g[i][j] = max(g[i - 1][j], f[i - 1][j - 1] + prices[i]);
}
}
}
int ret = 0;
for(int j = 0; j <= k; ++j){
ret = max(ret, g[n - 1][j]);
}
return ret;
}
};