股票问题
任务描述
大意就是有个数组 prices 代表每天股票价格,共 n 天,计算能获取的最大利润。
规则:总共能交易 i(i = 1,2,inf) 次(每次交易完成有 j 天的冷却时间,每次交易扣除 k 块钱手续费)
解决思路
动态规划三步曲:
-
定义数组的含义
这一步一般和题目要求有关。假设
dp[a][b][c]
代表第 a 天,总共允许交易 b 次,且此时手里有没有股票的状态为 c,则dp[n-1][i][0]
代表今天最后一天,总共能交易 i 次的最大利润。 -
状态方程(参考)
递推公式:
dp[a][b][0] = max(dp[a-1][b][0], dp[a-1][b][1] + prices[a])
/* 无事 卖 */
/*共a天,能买b次,手里没股票,两种情况*/
/*1:今天什么都没干,即和昨天情况没区别*/
/*2:今天把股票卖了,昨天肯定手里有票,利润加今天价格(昨天买了股票利润就减掉了昨天价格)*/
dp[a][b][1] = max(dp[a-1][b][1], dp[a-1][b-1][0] - prices[a])
/* 无事 买 */
/*共a天,能买b次,手里有股票,两种情况*/
/*1:今天什么都没干,即和昨天情况没区别*/
/*2:今天买股票,昨天肯定手里无票,利润减今天价格,到今天为止能买b次,昨天肯定为b-1次)*/
- 初始值
基础情况:
dp[-1][b][0] = 0 //-1代表还没开始
dp[-1][b][1] = -Infinity //没开始不可能有股票在手
dp[a][0][0] = 0 //共a天,不能买,利润0
dp[a][0][1] = -Infinity //不可能
leetcode题解
leetcode-121
只买一次
输入: [7,1,5,3,6,4]
输出: 5(6-1)
状态方程:
dp[a][1][0] = max(dp[a-1][1][0], dp[a-1][1][1] + prices[a])
dp[a][1][1] = max(dp[a-1][1][1], dp[a-1][0][0] - prices[a])
= max(dp[a-1][1][1], -prices[a])
题解:
class Solution {
public:
int maxProfit(vector<int>& prices) {
int dp_a10 = 0, dp_a11 = INT_MIN ,n=prices.capacity();
for (int i=0;i<n;i++) {
dp_a10 = max(dp_a10, dp_a11 + prices[i]);
dp_a11 = max(dp_a11, -prices[i]);
}
return dp_a10;
}
};
leetcode-122
买无限次
输入: [7,1,5,3,6,4]
输出: 7(5-1+6-3)
状态方程:
dp[a][inf][0] = max(dp[a-1][inf][0], dp[a-1][inf][1] + price)
dp[a][inf][1] = max(dp[a-1][inf][1], dp[a-1][inf][0] - price)
题解:
class Solution {
public:
int maxProfit(vector<int>& prices) {
int dp_a0 = 0, dp_a1 = INT_MIN ,n=prices.capacity();
for (int i=0;i<n;i++) {
int temp = dp_a0;//dp_a0和dp_a1相互影响,为了得到上一天的情况
dp_a0 = max(dp_a0, dp_a1 + prices[i]);
dp_a1 = max(dp_a1, temp-prices[i]);
}
return dp_a0;
}
};
leetcode-123
买两次
输入: [3,3,5,0,0,3,1,4]
输出: 6(3-0+4-1)
状态方程:
dp[a][2][0] = max(dp[a-1][2][0], dp[a-1][2][1] + price)
dp[a][2][1] = max(dp[a-1][2][1], dp[a-1][1][0] - price)
dp[a][1][0] = max(dp[a-1][1][0], dp[a-1][1][1] + prices[a])
dp[a][1][1] = max(dp[a-1][1][1], -prices[a])
题解:
class Solution {
public:
int maxProfit(vector<int>& prices) {
int dp_a20 = 0, dp_a10 = 0, dp_a21 = INT_MIN, dp_a11 = INT_MIN, n=prices.capacity();
for (int i=0;i<n;i++) {
dp_a20 = max(dp_a20, dp_a21 + prices[i]);
dp_a21 = max(dp_a21, dp_a10-prices[i]);
dp_a10 = max(dp_a10, dp_a11 + prices[i]);
dp_a11 = max(dp_a11, -prices[i]);
}
return dp_a20;
}
};
leetcode-188
买 b 次
状态方程
dp[a][b][0] = max(dp[a-1][b][0], dp[a-1][b][1] + price)
dp[a][b][1] = max(dp[a-1][b][1], dp[a-1][b-1][0] - price)
题解
class Solution {
public:
int maxProfit(int b, vector<int>& prices) {
int n = prices.capacity();
if (b >= n >> 1) {
int dp_a0 = 0, dp_a1 = INT_MIN;
for (int i=0;i<n;i++) {
int temp = dp_a0;//dp_a0和dp_a1相互影响,为了得到上一天的情况
dp_a0 = max(dp_a0, dp_a1 + prices[i]);
dp_a1 = max(dp_a1, temp-prices[i]);
}
return dp_a0;
}
vector<int> dp_ab0(b + 1,0) ;
vector<int> dp_ab1(b + 1, INT_MIN);
for (int i=0;i<n;i++) {
for (int j = b; j > 0; j--){
dp_ab0[j] = max(dp_ab0[j], dp_ab1[j] + prices[i]);
dp_ab1[j] = max(dp_ab1[j], dp_ab0[j - 1] - prices[i]);
}
}
return dp_ab0[b];
}
};