一、动态规划
动态规划问题解决的思路一般有以下几步:
-
确定状态:在动态规划问题中,状态一般就是我们需要优化的问题中的变量。状态需要满足无后效性(即某一阶段的状态一旦确定,就不受之后决策的影响)。
-
确定状态转移方程:状态转移方程是动态规划问题的关键。通过已知的状态和决策,求出下一步的状态。状态转移方程需要满足最优子结构性质(即一个问题的最优解包含其子问题的最优解)。
-
确定边界条件:边界条件是指动态规划问题中最小子问题的解,也就是动态规划过程中需要初始化的值。
-
确定求解顺序:动态规划问题一般有自底向上和自顶向下两种求解方式。自底向上需要先求解最小子问题的解,然后逐步求解更复杂的问题。自顶向下则是从最大的问题开始逐步拆解成小问题,直到求解最小子问题的解。
-
求解问题:根据求解顺序和状态转移方程,计算所有可能状态的值,最终得到问题的最优解。
-
子问题求解后,更新对应的样本节点的值为子问题求解值(比如第五个节点为伪节点的最大和存在第五个节点中)
需要注意的是,动态规划问题需要具有重叠子问题和无后效性,才能使用动态规划求解
举例说明动态规划的求解思路:
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
举例2:
假设有一个背包,可以容纳指定重量的物品,现在有一些物品,每个物品有各自的重量和价值,如下表所示:
物品编号 | 重量 | 价值 |
---|---|---|
1 | 2 | 6 |
2 | 2 | 3 |
3 | 6 | 5 |
4 | 5 | 4 |
5 | 4 | 6 |
现在要从这些物品中选择若干个放入背包,使得背包中物品的总重量不超过指定重量,同时背包中物品的总价值最大。这个问题可以用动态规划求解。
首先定义子问题:
设 $f(i,j)$ 表示前 $i$ 个物品放入容量为 $j$ 的背包中所能获得的最大价值。
接下来就可以进行状态转移了:
对于每个物品 $i$,有两种情况:
- 不选物品 $i$,则 $f(i,j) = f(i-1,j)$。
- 选物品 $i$,则 $f(i,j) = f(i-1,j-w_i)+v_i$。其中 $w_i$ 表示物品 $i$ 的重量,$v_i$ 表示物品 $i$ 的价值。
因此,可以得到状态转移方程:
$$ f(i,j) = \max(f(i-1,j), f(i-1,j-w_i)+v_i) $$
初始状态为 $f(0,j)=0$,表示没有物品放入背包时的最大价值为0。
最后,问题的解就是 $f(n,W)$,其中 $n$ 表示物品数量,$W$ 表示背包容量。
通过动态规划求解背包问题,可以得到以下表格:
物品编号 | 重量 | 价值 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|---|---|---|
1 | 2 | 6 | 0 | 0 | 6 | 6 | 6 | 6 | 6 |
2 | 2 | 3 | 0 | 0 | 6 | 6 | 9 | 9 | 9 |
3 | 6 | 5 | 0 | 0 | 6 | 6 | 9 | 9 | 9 |
4 | 5 | 4 | 0 | 0 | 6 | 6 | 9 | 9 | 10 |
5 | 4 | 6 | 0 | 0 | 6 | 6 | 9 | 10 | 12 |
表格中,每个格子表示在指定背包容量下,放入指定物品编号之前所能获得的最大价值。可以发现,最后一个格子 $f(5,6)=12$,即背包中物品的总价值最大为12。同时,可以根据表格中的信息,得到所选取的物品编号。