1. 动态规划与股票买卖问题入门
第一次接触股票买卖问题时,我盯着题目愣了半天——这不就是找最低点买入、最高点卖出吗?但仔细看OpenJudge NOI 2.6 8464这道题的要求,发现事情没那么简单:要在同一支股票上完成两次完整交易(买入-卖出-买入-卖出),且两次交易不能重叠。这就像在游乐场玩过山车,要想办法在两次起伏中抓到最大收益。
举个实际例子:假设股票价格序列是[3,5,1,4,6]。如果第一次在3买入5卖出,第二次在1买入6卖出,总利润是(5-3)+(6-1)=7。但如果第一次在1买入6卖出,第二次交易就无法进行,反而总利润只有5。这就是动态规划的用武之地——它帮我们系统化地考虑所有可能的交易组合。
动态规划解这类问题的核心在于状态定义。我们需要明确记录当前处于第几次交易、是否持有股票等关键信息。就像玩俄罗斯方块时要同时考虑当前方块和下一个方块的位置关系,股票问题也需要同时跟踪多个状态维度。
2. 状态设计与转移方程剖析
2.1 关键状态定义
解决这个问题需要设计三维状态:
dp[i][k][0/1]表示第i天、已完成k次交易(0≤k≤2)、当前未持有/持有股票(0/1)时的最大利润
具体来说:
dp[i][1][0]表示第i天完成1次交易后不持股dp[i][1][1]表示第i天完成1次交易后仍持股dp[i][2][0]表示第i天完成2次交易(最终状态)
这种设计就像给每个交易阶段打了标签,让我们能清晰区分第一次和第二次交易的收益。
2.2 状态转移方程推导
状态转移需要考虑四种基本操作:
- 保持不动:延续前一天的持股状态
- 买入操作:消耗一次交易机会,现金减少
- 卖出操作:完成一次交易,现金增加
- 交易次数限制:最多完成两次完整交易
用数学表达式表示:
# 初始化
dp[0][0][0] = 0 # 第0天未开始交易
dp[0][0][1] = -prices[0] # 第0天买入
dp[0][1][0] = -inf # 不可能状态
dp[0]


561

被折叠的 条评论
为什么被折叠?



