动态规划构造dp数组的思路:构造的dp数组要含义明确(dp数组的含义决定了后续代码的结构),且要便于归纳(说白了就是从已知推导未知,便于寻找状态转移),要明确base case是什么(这一点很重要),和base case同等重要的是end case也就是要求的结果在数组中的那个位置(不同的问题对应的解存在位置不同,有的是dp[m][n](右下角),有的是dp[0][n](右上角),要具体问题具体分析)。
确定了dp数组的含义之后,就要寻找其base case,然后分析其状态转移情况,用正确的遍历方式(正向遍历,反向遍历,斜向遍历(要确保用已知的状态求未知的状态))确保正确的状态转移。
明确「状态」 -> 定义 dp 数组/函数的含义 -> 明确「选择」-> 明确 base case
状态转移⽅程 写状态转移⽅程很简单,⾸先要找到所有「状态」和每个状态可以做的「选 择」,然后择优
比如鼓楼扔鸡蛋问题的「状态」很明显,就是当前拥有的鸡蛋数 K 和需要测试的楼层数 N 。随 着测试的进⾏,鸡蛋个数可能减少,楼层的搜索范围会减⼩,这就是状态的 变化,「选择」其实就是去选择哪层楼扔鸡蛋。
现在明确了「状态」和「选择」,动态规划的基本思路就形成了:肯定是个 ⼆维的 dp 数组或者带有两个状态参数的 dp 函数来表⽰状态转移;外加 ⼀个 for 循环来遍历所有选择,择最优的选择更新状态:
d
p
(
K
,
N
)
=
min
0
<
=
i
<
=
N
max
d
p
(
K
−
1
,
i
−
1
)
,
d
p
(
K
,
N
−
i
)
+
1
dp(K, N) = \min_{0 <= i <= N}{\max{dp(K - 1, i - 1), dp(K, N - i)} + 1}
dp(K,N)=0<=i<=Nminmaxdp(K−1,i−1),dp(K,N−i)+1
总而言之,要想快速准确地构造合适的dp数组,唯有勤学苦练,见多识广,举一反三,融会贯通。