(六)动态规划

基础动态规划

\(1.1\)[NOIP2010 提高组] 乌龟棋 - 洛谷

记录 \(f[i][j][k][l]\) 表示每种卡片用的个数即可,距离可以现算。

评测记录 - 洛谷

\(1.2\)[HAOI2006]数字序列 - 洛谷

开始想了个 \(n*\max{a[i]}\) 的屑做法,只有 \(27~\text{pts}\)评测记录 - 洛谷

正解:可以保留 \(a[i]\)\(a[j]\) 的充分必要条件是 \(a[j]-a[i]\ge j-i,(j>=i)\)

移项得 \(a[j]-j\ge a[i]-i\) ,设 \(b[i]=a[i]-i\),问题一就转化为求 \(b[i]\) 的最长不下降子序列。

对于第二问,设 \(pre_i\) 表示 \(b_i\)\(b_{pre_i}\) 转移而来。

\(\mathrm{Lemma}:\) \(b_i\)\(b_{pre_i}\) 存在一个分界点 \(k\) 满足 \(\forall j\in [b_{pre_i},b_k], b_j=b_{pre_i}\)\(\forall l\in [b_{k+1},b_i],b_l=b_i\)

证明:

考虑 \(b_{pre_i}\to b_i\) 之间的赋值情况,一定可以被表示为台阶状。

对于 \(cnt_{>b_i} > cnt_{<b_{pre_i}}\),可以将台阶向上移动到与下一个平齐。

对于 \(cnt_{>b_i}<cnt_{<b_{pre_i}}\),可以将台阶向下移动到与上一个台阶平齐。

\(Q.E.D\)

枚举每个区间的 \(k\),即可计算总代价。

具体实现时,给 \(b\) 开头加一个极小值,末尾加一个极大值,即 \(b[0]=-INF, b[n+1]=INF\)

这样,即可对序列 \(b\) 运用上述结论,否则对于 \(b[1]\) 极大或 \(b[n]\) 极小的情况就会出错。

调试惨烈(

评测记录 - 洛谷

\(1.3\)[SCOI2003]字符串折叠 - 洛谷

区间 \(DP\)\(f[i][j]=\min\left\{f[i][k] + f[k+1][j]\right\}\)

考虑折叠的情况,枚举 \(j-i+1\) 的约数,检验是否可以转移即可。

评测记录 - 洛谷

\(1.4\)[BalticOI 2008]选举 Easy - 洛谷

此题即为 \(\displaystyle S-a_{\min}\le \frac{tot}{2}\) ,设 \(f[i][j]\) 表示在前 \(i\) 个中选择人数和为 \(j\) 的党派是否可行。

设计转移方程为 \(\displaystyle f[i][j] \mid = f[i][j-a[i]]~(j-a[i]\le \frac{tot}{2})\) 。事先将 \(a[i]\) 排序即可满足题意条件:每次取出的 \(a[i]\) 均为最小的。

压掉一维后,时间复杂度为 \(O(nV)\) ,空间复杂度为 \(O(n+V)\)

评测记录 - 洛谷

\(1.5\)[SCOI2009]粉刷匠 - 洛谷

\(f[i][j]\) 表示前 \(i\) 块木板,粉刷 \(j\) 次的最大正确数,\(G[i][j][k]\) 为第 \(i\) 块模板前 \(j\) 个格子,粉刷 \(k\) 次所能达到的最大正确数。

于是 \(f[i][j]=f[i - 1][j - l] + G[i][m][l]\)\(G[i][j][k]=G[i][j-l][k-1]+Calc(l, j)\),转移即可。

评测记录 - 洛谷

\(1.6\)[CSP-J2020] 方格取数 - 洛谷

\(up[i][j], down[i][j], left[i][j]\) 分别表示从上,下,左到点 \((i,j)\) 的最大点权。因为只能向右不能向左,于是以列为阶段,转移即可。

评测记录 - 洛谷

\(1.7\)[SCOI2007]压缩 - 洛谷

一开始拿到这道题的时候,以为和 [SCOI2003]字符串折叠 - 洛谷 是一样的。但是仔细思考(WA了两发)后发现,其实是不能嵌套的,因为每个 \(R\) 只会与离他最近的 \(M\) 产生关系。

考虑设 \(dp[i][j][0]\) 表示 \([i,j]\) 之间没有 \(M\) 的最短压缩长度,\(dp[i][j][1]\) 表示 \([i,j]\) 之间有 \(M\) 的最短压缩长度。

\(dp[i][j][0] = \min\{dp[i][k][0]+j-k\}\)

\(dp[i][j][1]=\min\{\min(dp[i][k][0],dp[i][k][1])+\min(dp[k+1][r][0],dp[k+1][r][1])+1\}\)

注意到一个 \(M\) 会把原序列分割为互不干扰的两段,于是枚举 \(M\) 的出现位置就得到了 \(dp[i][j][1]\) 的转移方程。

由于 \(i-1\) 位置可以放 \(M\),于是 \(f[i][j][0]\) 还可以由 \(1+f[i][mid][0]\) 转移得到,\(\mathrm{iff}~s[l\to mid]=s[mid + 1\to r]\)

评测记录 - 洛谷

\(1.8\)垃圾陷阱 - 洛谷

首先按照时间排序是必须的。

\(f[i][j]\) 表示在第 \(i\) 个选择后,还剩 \(j\) 点生命所能达到的最大高度。

有转移 \(f[i][j]=\max(f[i-1][j+delta-duration[i]],t[i-1][j+delta]+height[i])\)

注意转移边界问题。

评测记录 - 洛谷

\(1.9\)[BJOI2019] 排兵布阵 - 洛谷

小清新 \(DP\) 题。设 \(f[i][j]\) 表示考虑前 \(i\) 个城堡,派出 \(j\) 的兵力所能产生的最大收益,排序后转移即可。越来越顺手了呢。

写代码记得检查数组开的范围。

评测记录 - 洛谷

\(1.10\)不听话的机器人 - 洛谷

\(f[i][x][y][k]\) 表示考虑前 \(i\) 个指令·,目前在 \((x,y)\) 方向为 \(k\) 的最少违背多少条指令,转移即可。

实现较为繁琐。

评测记录 - 洛谷

树形 DP

\(2.1\)[CTSC1997] 选课 - 洛谷

题意可以抽象为一个森林。

\(f[i][j]\) 表示在以 \(i\) 为根的子树中选出 \(j\) 个能得到的最大学分。

不难发现,满足要求的就是一个与 \(i\) 相连的连通块。

那么考虑前缀和优化:\(f[i][j]=\max\{f[i][k] + f[son][j-k]\}\) 。其中 \(f[i][j]\) 表示已经转移的子树的答案。转移边界即为 \(f[i][1]=val[i]\) 。为防止后效性,交换一下枚举顺序和方向即可。

评测记录 - 洛谷

\(2.2\)ρars/ey - 洛谷

好像考察的是树形背包的上下界优化。不过我不懂,于是由于上下界没卡紧,导致第一次提交 \(70pts\)

树形背包很好想,设 \(f[i][j]\) 表示在以 \(i\) 为根的子树内,保留大小为 \(j\) 的块的最小代价,转移即可。

每次均为 \(sz[x] * sz[y]\) 的,可以证明复杂度正确。

树上背包的上下界优化 - ouuan的博客

找了篇博客,上面有证明。

至于我为什么假了,可以参见 100pts 评测 - 洛谷70pts 评测 - 洛谷 两次提交。

上下界一定要卡紧,最好采用 \(f[i+j]=\dots f[i] + f[j]\) 这种写法,不容易挂上下界。

写的太丑了,重新放一个:评测记录 - 洛谷

\(2.3\)重建道路 - 洛谷

又是一道树形背包,但是我却足足写了两个小时。

时间主要耗费在了写对拍用的暴力上,屡次对拍,挂的却是暴力,侧面反应代码能力不足。

暴力就应该思维清晰,一发冲过。

评测记录 - 洛谷

\(2.4\)[ZJOI2007] 时态同步 - 洛谷

将图看成以激发器 \(S\) 为根的一棵树。

可以先若在以 \(S\) 为根的树中时态同步,则在其任意一棵子树中,时态必定也同步。

考虑树形 \(DP\):设 \(F(x)\) 表示使以 \(x\) 为根的子树时态同步所需的最小次数,\(path(x)\) 表示时态同步时,从 \(x\) 到叶子节点的路径长度。

再设 \(MaxPath\) 表示未经操作时,\(x\) 到叶子节点的最长路径。

容易得出转移方程:\(F(x)=\sum_{son\in x}{F(son)}+\sum_{son\in x}{MaxPath-path(son)-edge(x,son)}\)

评测记录 - 洛谷

换根 DP

\(2.5\)[POI2008] STA-Station

预处理以 \(1\) 为根时的情况,每次转移考虑根节点由父节点变动到子节点带来的影响即可。

评测记录 - 洛谷

\(2.6\)[USACO10MAR] Great Cow Gathering G

与上一题相比,这道题带上了点权。转移时多考虑一些东西就行了。

评测记录 - 洛谷

\(2.7\)Centroids

树的重心的定义:一个有 \(n\) 个节点的树,删去该节点过后,每个连通块的均小于 \(\lfloor\dfrac{n}{2}\rfloor\)

原操作其实可以看做子树的移接。

对于此题,以原树的重心为根预处理出子树大小。若一个节点 \(x\) 经操作后能成为重心,则考虑除 \(x\) 的子树外的所有节点,设最大不超过 \(\lfloor\dfrac{n}{2}\rfloor\) 的子树大小为 \(S\),那么若 \(n-S-sz[x]\le \lfloor\dfrac{n}{2}\rfloor\),则 \(x\) 能成为根节点,否则不行。

评测记录 - 洛谷

计数 DP

\(3.1\)[BJOI2017]机动训练

考虑平方的意义,即:两个人走相同的地形的方案数。

把情况分为 \(4\) 类,即(右、上、右上),(左、上、左上)、(右、下、右下)、(左、下、左下)。发现只向单个方向走的情况会重复计算,最后减去即可。

\(DP\) 转移顺序难以确定,采用记忆化搜索实现。

评测记录 - 洛谷

\(3.2\)Vasya and Array

\(f[i][j]\) 表示考虑前 \(i\) 位,第 \(i\) 位为 \(j\) 的合法方案数。

\(sf[i]=\sum\limits_{j=1}^{k}{f[i][j]}\),考虑如下容斥:

\(f[i][j]=sf[i-1]-sf[i-len]+f[i-len][j]\)

\(sf[i-len]\) 即令 \(i-len+1\sim i\) 中的数均为 \(j\) ,本来就有不合法的,重复减去的 \(f[i-len][j]\)\(i-len\sim i-1\) 均为 \(j\)) 加上即可。

评测记录 - 洛谷

单调队列优化 DP

\(4.1\)切蛋糕 - 洛谷

前缀和过后问题就变成了对于每个 \(i\),求 \(\forall j\in [i-m,i-1]\) 使得 \(pre[j]\) 最大。

于是就变成了一个可以由单调队列维护的问题。

评测记录 - 洛谷

\(4.2\)Watching Fireworks is Fun - CF372C

典型的单调队列优化 \(DP\)。设 \(f[i][j]\) 表示在第 \(i\) 个烟花的时候,处于第 \(j\) 个位置的最大值。

发现其可以由 \(f[i-1][k], k\in [j-(d*\Delta t),j+(d*\Delta t)]\) 转移而来。

固定长度区间最值,单调队列优化即可。

评测记录 - CF

\(4.3\)[POI2014]PTA-Little Bird - 洛谷

朴素 \(DP\)\(f[i]\) 表示停留在 \(i\) 时的最小劳累值。于是 \(f[i]=\min\limits_{j\ge i-k}\left\{f[j]+(d[j]\le d[i])\right\}\)

确定单调队列更新顺序,先 \(pop\),再 \(query\),再 \(push\) 即可。

评测记录 - 洛谷

\(4.5\)

posted @ 2022-10-16 14:35  mklzc  阅读(38)  评论(0编辑  收藏  举报