【动态规划】“新手动态规划合集”题解
动态规划三要素
阶段,状态,决策
动态规划经典模型
LIS(最长上升子序列)
给定长度为 \(N\) 的序列 \(A[i]\),求出其最长上升子序列的长度。(以不严格上升为例)
-
阶段:已经处理的序列长度 \(i\)
-
状态:\(f[i]\) 表示以 \(A[i]\) 结尾的 LIS 长度
-
转移
这个转移是 \(\Theta(N^2)\) 的。事实上可以通过二分来优化到 \(\Theta(N\log N)\),但是不甚通用。
比较通用的做法是用 cdq 分治 进行优化。时间复杂度 \(\Theta(N\log^2 N)\)。
LCS(最长公共子序列)
给定长度为 \(N\) 的序列 \(A[i]\) 和长度为 \(M\) 的序列 \(B[i]\),求出其 LCS 长度。
-
阶段:\(A\) 已经处理的长度 \(i\),\(B\) 已经处理的长度 \(j\)
-
状态:\(f[i,j]\) 表示 \(A[1..i]\) 与 \(B[1..j]\) 的 LCS 长度
-
转移
时间复杂度 \(\Theta(NM)\)。
新手动态规划合集题单题解
P1359 租用游艇
给定从 \(i\) 到 \(j\) 的代价 \(w[i,j]\)(\(i\lt j\)),求出从 \(1\) 地到 \(N\) 地的最小代价。
设 \(f[i]\) 表示从 \(1\) 到 \(i\) 的最小代价。转移方程:
初值:\(f[1]=0\),其余均为正无穷。目标:\(f[n]\)。
P1060 [NOIP2006 普及组] 开心的金明
有 \(n\) 元,\(m\) 个物品。第 \(i\) 个物品价值为 \(v[i]\),权值为 \(w[i]\)。选定一些物品,在 \(\sum w[i]\leq n\) 的前提下,\(\sum v[i]\times w[i]\) 最大。
这本质上是一个 0-1 背包问题。每个物品质量为 \(v[i]\),价值为 \(v[i]\times w[i]\)。
于是设 \(f[i,j]\) 为考虑到第 \(i\) 个物品时,花费 \(j\) 元所得最大值。于是
然后可以利用滚动数组优化,注意别滚反了。
P1802 5 倍经验日
有 \(x\) 瓶药,\(n\) 个人,对第 \(i\) 个人使用 \(m\) 瓶时,获得经验为
求出获得经验最大值。
这也是一个背包模型。设 \(f[i,j]\) 为考虑到第 \(i\) 个人,使用 \(j\) 瓶药时的经验最大值。于是
目标:\(f[n,m]\)。
[NOIP2001 普及组] 装箱问题
有一个箱子容量为 \(V\),同时有 \(n\) 个物品,每个物品有一个体积。从 \(n\) 个物品中,任取若干个装入箱内(也可以不取),使箱子的剩余空间最小,输出这个最小值。
我们设 \(f[i,j]=0/1\) 表示当前取到第 \(i\) 个物品,剩余空间为 \(j\) 的状态是否可行。
于是我们得到
其中 \(V_i\) 为物品 \(i\) 的体积。
找到一个最小的 \(j\),使得 \(f[n,j]=true\),即为所求。
P1048 [NOIP2005 普及组] 采药(0-1背包)
有 \(n\) 个物品,第 \(i\) 个物品的价值为 \(val[i]\),质量为 \(weight[i]\),背包能承载的最大质量为 \(m\),每个物品可以取也可以不取,求承载物品的最大价值和。
我们设 \(f[i,j]\) 表示考虑到第 \(i\) 个物品时,使用 \(j\) 的背包质量能够承载的物品的最大价值和。
显然
前一项表示选,后一项表示不选物品 \(i\)。
可以通过滚动数组将空间占用压缩到 \(\mathcal{O}(n)\)。