【动态规划】“新手动态规划合集”题解

动态规划三要素

阶段,状态,决策

动态规划经典模型

LIS(最长上升子序列)

给定长度为 \(N\) 的序列 \(A[i]\),求出其最长上升子序列的长度。(以不严格上升为例)

  • 阶段:已经处理的序列长度 \(i\)

  • 状态:\(f[i]\) 表示以 \(A[i]\) 结尾的 LIS 长度

  • 转移

\[f[i]=\max\limits_{j\in\left[1,i-1\right]\wedge A[j]\leq A[i]}f[j]+1 \]

这个转移是 \(\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 长度

  • 转移

\[f[i,j]= \max\begin{cases} \max(f[i-1,j],f[i,j-1]), \\ f[i-1,j-1]+1, \text{if } A[i]=B[j] \end{cases}\]

时间复杂度 \(\Theta(NM)\)

新手动态规划合集题单题解

P1359 租用游艇

给定从 \(i\)\(j\) 的代价 \(w[i,j]\)\(i\lt j\)),求出从 \(1\) 地到 \(N\) 地的最小代价。

\(f[i]\) 表示从 \(1\)\(i\) 的最小代价。转移方程:

\[f[i]=\max\limits_{j\in[1,i-1]}\left(f[j]+w[j,i]\right) \]

初值:\(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\) 元所得最大值。于是

\[f[i, j]=\max(f[i,j],f[i-1,j-v[i]]+v[i]\times w[i]) \]

然后可以利用滚动数组优化,注意别滚反了

P1802 5 倍经验日

\(x\) 瓶药,\(n\) 个人,对第 \(i\) 个人使用 \(m\) 瓶时,获得经验为

\[\begin{cases} win[i], m \geq use[i] \\ lose[i], m \lt use[i] \end{cases} \]

求出获得经验最大值。

这也是一个背包模型。设 \(f[i,j]\) 为考虑到第 \(i\) 个人,使用 \(j\) 瓶药时的经验最大值。于是

\[f[i,j]=\max\begin{cases} f[i-1,j-use[i]]+win[i], (\text{if} j\geq use[i])\\ f[i-1,j]+lose[i] \end{cases} \]

目标:\(f[n,m]\)

[NOIP2001 普及组] 装箱问题

有一个箱子容量为 \(V\),同时有 \(n\) 个物品,每个物品有一个体积。从 \(n\) 个物品中,任取若干个装入箱内(也可以不取),使箱子的剩余空间最小,输出这个最小值。

我们设 \(f[i,j]=0/1\) 表示当前取到第 \(i\) 个物品,剩余空间为 \(j\) 的状态是否可行。

于是我们得到

\[f[i,j]=f[i,j] \operatorname{or} f[i-1,j+V_i] \]

其中 \(V_i\) 为物品 \(i\) 的体积。

找到一个最小的 \(j\),使得 \(f[n,j]=true\),即为所求。

P1048 [NOIP2005 普及组] 采药(0-1背包)

\(n\) 个物品,第 \(i\) 个物品的价值为 \(val[i]\),质量为 \(weight[i]\),背包能承载的最大质量为 \(m\),每个物品可以取也可以不取,求承载物品的最大价值和。

我们设 \(f[i,j]\) 表示考虑到第 \(i\) 个物品时,使用 \(j\) 的背包质量能够承载的物品的最大价值和。

显然

\[f[i,j]=\max(f[i-1,j],f[i-1,j-weight[i]]+val[i]) \]

前一项表示选,后一项表示不选物品 \(i\)

可以通过滚动数组将空间占用压缩到 \(\mathcal{O}(n)\)

posted @ 2023-09-03 15:33  Starrykiller  阅读(43)  评论(0)    收藏  举报