状态机模型原理
- 包含多个待选状态,不同的状态之间有相互转化的方法,我们可以借助这些转化的手段,达成状态之间的相互转移
- 模型基础: 图论
- 建模: 把状态抽象成点,转换的方法抽象成边
- 理论要素:
1,状态入口: 合法初始化
2,状态出口: 答案生成位
一,01(双状态)
简化:状态附加一维,维度大小2
要素:
f
[
i
]
[
0
]
f[i][0]
f[i][0] 表示当前状态不选 ,
f
[
i
]
[
1
]
f[i][1 ]
f[i][1] 表示当前状态选
分析: 表示中的01相当于已经做出了决策,接下来,借助图论的思想考虑转移的手段,也就是走图上的带权边
1,01背包变形
题意:01背包,不能选择相邻的物品
分析: 对于第
i
i
i天的情况,只有选或者不选
- 不选则可以维持现状,前面的物品选了没选都无所谓
- 选了的话,前面的物品肯定不能选
转移方程:
f
[
i
]
[
1
]
=
f
[
i
−
1
]
+
w
[
i
]
f[i][1]=f[i-1]+w[i]
f[i][1]=f[i−1]+w[i],
f
[
i
]
[
0
]
=
m
a
x
(
f
[
i
−
1
]
[
0
]
,
f
[
i
−
1
]
[
1
]
)
f[i][0]=max(f[i-1][0],f[i-1][1])
f[i][0]=max(f[i−1][0],f[i−1][1])
注意初始化: 第0个物品的时候选了0个是合法的,选了第0个本身就是不合法的,需要阻止他转移,题中求最大方案,设成
−
I
N
F
-INF
−INF
int main()
{
f[0][0]=0;
f[0][1]=-INF;
for (int i = 1; i <= n; i ++ )
{
f[i][1]=f[i-1][0]+w[i];
f[i][0]=max(f[i-1][0],f[i-1][1]);
}
printf("%d\n",max(f[n][0],f[n][1]));
}
2,股票问题(leetcode)
题意:已知
n
n
n 天之内的股价,控制
k
k
k 次交易的上限, 需要控制买进卖出来获取最大收益
注意:一次买入一次卖出为一笔 合法交易,且不能同时产生多笔交易(必须在再次购买前出售掉之前的股票)
分析:
- 有买有卖,线性特征
- 持和未持,转移时需要考虑前面的数据的持或未持的状态,有必要记录,开状态机
- 注意一波初始化
- 入口在0,出口保证贪心的选择0
状态转移:
f
[
i
]
[
j
]
[
0
]
=
m
a
x
(
f
[
i
−
1
]
[
j
]
[
0
]
,
f
[
i
−
1
]
[
j
−
1
]
[
1
]
+
w
[
i
]
)
f[i][j][0] = max(f[i-1][j][0], f[i - 1][j - 1][1] + w[i])
f[i][j][0]=max(f[i−1][j][0],f[i−1][j−1][1]+w[i])
f
[
i
]
[
j
]
[
1
]
=
m
a
x
(
f
[
i
−
1
]
[
j
]
[
1
]
,
f
[
i
−
1
]
[
j
]
[
0
]
−
w
[
i
]
)
f[i][j][1] = max(f[i - 1][j][1], f[i - 1][j ][0] - w[i])
f[i][j][1]=max(f[i−1][j][1],f[i−1][j][0]−w[i])
二,012(三状态)
题意:同样的股票问题,现有卖完后的一天冷冻期
- 1,(j=0) 当前没有股票,且不处于冷冻期 (空仓)
- 2,(j=1) 当前有股票 (持仓)
- 3,(j=2) 当前没有股票,且处于冷冻期 (冷冻期)
分析略
AC code 及题目
彩铅大佬的讲解