以下均以 01 背包举例。

状态表示

将每一个状态看作一个集合集的属性

\(f[i,j]\) 表示前 \(i\) 个物品中总体积为 \(j\) 的物品集合集的元素大小和的最大值(属性)。

\(e.g.\)


\[id:1,2,3\]


\[w_i:4,5,9\]


\[v_i:6,8,7\]


\[f[3,9]\to\{\{1,2\},\{3\}\}\]


其中 \(\{1,2\}\) 的价值和最大,为 \(6+8=14\),故 \(f[3,9]=14\)

常见的属性有:大小、最值、和、乘积、异或和……

状态转移

对集合集中集合的划分。

将 \(f[i,j]\) 的集合集划分成包含 \(i\) 物品的集合和不包含 \(i\) 物品的集合。

两种情况分别对应 \(f[i-1,j]\) 和 \(f[i-1,j-w_i]+v_i\)。

所以状态转移方程为 \(f[i,j]=\max(f[i-1,j],f[i-1,j-w_i]+v_i)\)。

\(e.g.\)


\[id:1,2,3,4\]


\[w_i:4,5,9,8\]


\[v_i:6,8,7,1\]


\[f[4,13]\to\{\color{blue}{\{1,3\}},\color{red}{\{2,4\}}\}\]


蓝色为不含 \(i\) 的,红色为含 \(i\) 的。

再思考,可以用滚动数组优化空间复杂度。


DP 问题的一般分析方法_空间复杂度