动态规划分析问题五步曲
不清楚动态规划分析问题是哪关键的五步的少年们可以移步到
链接: 动态规划算法基础
这篇文章非常详细的介绍了动态规划算法是如何分析和解决问题的
题目概述
链接: 买股票的最佳时机II
- 状态表示(题目要求+自己的经验)
本题状态:分析第i个位置,发现在第i个位置我们可以处于可买入或可卖出状态
所以本题应该有两个状态表示
buy[i] : 表示第i个位置为可买入状态(即在i位置时没持有股票)可获得的最大利润
sell[i] : 表示第i个位置为可出售状态(即在i位置时持有股票)可获得的最大利润
利用状态机推导状态转移方程式
再推导状态转移方程式之前,不妨列出所有状态之间的转换关系
这些状态之间的转换关系,就被称之为状态机
本题 可买入和可卖出状态的状态机如下
- 状态转移方程推导
对i位置进行分类讨论,再配合状态机的使用
当i位置为可买入状态,第i-1个位置可能为可买入状态或可卖出状态
当i位置为可卖出状态,第i-1个位置可能为可买入状态或可卖出状态
(要注意从可买入状态到可卖出状态和可卖出状态到可买入状态的转换)
- 初始化(防止越界+结合状态表示初始化)
根据状态转移方程,当i = 0时会发生越界
根据状态表示 :
buy[0] : 要使得第一个位置为可买入状态,那么不买入股票就行 buy[0] = 0;
sell[0] : 要使得第一个位置为可卖出状态,那么一定要买入第一份股票 sell[0] = 0-prices[0] ;
- 填表顺序(分析要填i位置前一个依赖状态的位置)
本题两个dp表显然都是从左到右填表
- 返回值(由题目要求来)
最后一个位置处于可卖出状态,一定不是最大利润
buy[m-1] > sell[m-1] 恒成立,所以最后返回的是 buy[m-1] ;
代码编写
有了动态规划五步曲我们就可以写出非常优雅的代码了
int maxProfit(vector<int>& prices) {
int n = prices.size();
if(n == 0) return 0;
vector<int> buy(n);
auto sell = buy;
auto ice = buy;
sell[0] -= prices[0];
for(int i = 1 ; i < n ; i++)
{
buy[i] = max(buy[i-1],ice[i-1]);
sell[i] = max(buy[i-1]-prices[i],sell[i-1]);
ice[i] = sell[i-1] + prices[i];
}
return max(ice[n-1],buy[n-1]);
}
少年,今天你又进步了一点点哟,明天继续加油吧