蓝桥杯算法解析(四):动态规划进阶——股票问题与状态机模型
前言
动态规划(DP)的进阶问题往往让选手望而生畏,尤其是涉及多状态决策的场景。今天我们将通过股票买卖这一经典问题,深入讲解状态机模型在DP中的应用。据统计,这类问题在蓝桥杯国赛中的出现频率高达28%。
🔥 本文包含:
- 股票买卖问题的6种变体
- 状态机模型的通用解题框架
- 3道蓝桥杯真题的降维打击解法
一、股票买卖问题全家桶
1.1 问题变体一览表
| 问题类型 | 交易次数 | 冷却时间 | 手续费 | 典型例题 |
|---|---|---|---|---|
| 单次交易 | 1 | 无 | 无 | 剑指Offer 63 |
| 无限次交易 | ∞ | 无 | 无 | 122.买卖股票II |
| 含冷冻期 | ∞ | 1天 | 无 | 309.最佳买卖时机 |
| 含手续费 | ∞ | 无 | 有 | 714.买卖股票含手续费 |
| 限制交易次数 | k | 无 | 无 | 123.买卖股票III |
| 隔天交易 | ∞ | 1天 | 无 | 蓝桥杯2020省赛 |
1.2 状态机模型图解
rest
↗ ↖
buy ← hold → sell
↖ ↗
cooldown
状态转移表:
| 当前状态 | 可执行操作 | 转移后状态 |
|---|---|---|
| 空仓 | 买入/休息 | 持有/空仓 |
| 持有 | 卖出/休息 | 空仓/持有 |
| 冷冻期 | 只能休息 | 空仓 |
二、通用解法框架
2.1 三维DP模板
def maxProfit(prices):
n = len(prices)
# dp[i][k][0/1]:第i天最多k次交易时的最大收益(0不持有,1持有)
dp = [[[0]*2 for _ in range(K+1)] for _ in range(n+1)]
# 初始化
for k in range(K+1):
dp[0][k][1] = -float('inf')
for i in range(1, n+1):
for k in range(1, K+1):
dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1] + prices[i-1])
dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0] - prices[i-1])
return dp[n][K][0]
2.2 空间优化(滚动数组)
def maxProfit(prices):
dp_i0, dp_i1 = 0, -float('inf')
for price in prices:
dp_i0, dp_i1 = max(dp_i0, dp_i1 + price), max(dp_i1, dp_i0 - price)
return dp_i0
三、蓝桥杯真题实战
3.1 2020年省赛-股票交易
题目描述:
T+1交易规则(当天买入次日才能卖出),可进行无限次交易,求最大利润。
状态转移方程:
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i]) # 不持有
dp[i][1] = max(dp[i-1][1], dp[i-2][0] - prices[i]) # 持有(需间隔一天)
AC代码:
def maxProfit(prices):
n = len(prices)
if n < 2: return 0
dp = [[0]*2 for _ in range(n)]
dp[0][1] = -prices[0]
dp[1][0] = max(0, prices[1] - prices[0])
dp[1][1] = max(-prices[0], -prices[1])
for i in range(2, n):
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])
dp[i][1] = max(dp[i-1][1], dp[i-2][0] - prices[i])
return dp[-1][0]
3.2 状态压缩优化版
def maxProfit(prices):
dp_i0, dp_i1 = 0, -float('inf')
dp_pre0 = 0 # 代表dp[i-2][0]
for price in prices:
temp = dp_i0
dp_i0 = max(dp_i0, dp_i1 + price)
dp_i1 = max(dp_i1, dp_pre0 - price)
dp_pre0 = temp
return dp_i0
四、状态机模型扩展应用
4.1 打家劫舍问题
状态定义:
dp[i][0]:不偷第i家的最大收益dp[i][1]:偷第i家的最大收益
状态转移:
dp[i][0] = max(dp[i-1][0], dp[i-1][1])
dp[i][1] = dp[i-1][0] + nums[i]
4.2 航班预订统计
状态转移表:
| 操作类型 | 状态变化 |
|---|---|
| 预订 | 座位数 -= 预订量 |
| 查询 | 返回当前剩余座位数 |
五、下期预告
**《图论算法精讲:从邻接表到Dijkstra》**将涵盖:
- 图的5种存储方式对比
- 最短路径算法全家桶
- 拓扑排序的妙用
思考题:如果股票交易增加2小时持仓限制(买入后至少持有2小时才能卖出),该如何修改状态转移方程?欢迎在评论区分享你的解法!
:动态规划进阶——股票问题与状态机模型&spm=1001.2101.3001.5002&articleId=147457015&d=1&t=3&u=3c10eb3a1e0b4f228ac4ad50136aaa17)
1328

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



