其他分享
首页 > 其他分享> > 动态规划题目选解(二)

动态规划题目选解(二)

作者:互联网

上一个写太长导致 typora 卡爆了,只好新开一个。。

动态规划题目选解(一)


CF730J Bottles Present 4

首先 \(k\) 很好算出来:记 \(\sum a_i=\text{sum}\),从大到小贪心选到 \(\sum b_i\ge \text{sum}\) 即可。

考虑 \(t\) 怎么算:如果我们选出的这 \(k\) 个瓶子内的水量分别为 \(x_1,x_2,\cdots,x_k\),容量分别为 \(y_1,y_2,\cdots,y_k\),那么:

要让 \(t\) 尽可能小,那就是让 \(\sum{x_i}\) 尽可能大。

发现这个数据范围小的一批,因此可以考虑暴力 dp。

设 \(F(i,j,S)\) 为:从前 \(i\) 个中选出 \(j\) 个,并且选出的这些的 \(b\) 值之和为 \(S\) 时,\(\sum x_i\) 的最大值;若不存在这样的方案,则 \(F(i,j,S)=-\infty\)。

转移的时候枚举最后一个数选不选,得到

\[F(i,j,S)=\max(F(i-1,j,S),F(i-1,j-1,S-b_i)+a_i) \]

可以滚动数组滚掉一维。

由于序列中所有数的和不超过 \(O(nV)\),因此复杂度为 \(O(n^2\cdot nV)=O(n^3V)\),其中 \(V=100\) 为值域。


CF299D Towers Present 6

可以发现,最终得到的序列中每个数都由原序列中一个区间内的塔合并而来。

那么考虑设 \(F(i,j)\) 表示前 \(i\) 个塔,并且合并后最后一个塔由 \([j,i]\) 中的塔合起来时的最小代价。

转移考虑枚举上一个塔合并到哪里,有

\[F(i,j)=\min\left\{F(j-1,k)+(i-j)\left|\sum_{x=k}^{j-1}h_x\le \sum_{x=j}^ih_x\right.\right\} \]

显然满足条件的 \(k\) 是一个区间,因此可以二分同时维护后缀和简单做到 \(O(n^2\log n)\)。

设 \(S_i=\sum_{j=1}^ih_j\),那么后面那个条件相当于 \(S_i-S_{j-1}\ge S_{j-1}-S_{k-1}\)。

移项得到 \(2S_{j-1}-S_i\le S_{k-1}\),由于 \(h_i>0\) 有 \(S_i\) 递增,因此可以维护一个指针 \(k\) 不断移动,即可做到 \(O(n^2)\)。

我偷懒写了带 \(\log\) 的做法 2333 AC Code


CF1051D Biocolorings Present 4

考虑暴力状压最后一列:设 \(F(i,j,S)\) 为,考虑前 \(i\) 列,有 \(j\) 个连通块,最后一列的状态为 \(S\)(\(S=00/01/10/11\))的方案数。

转移的时候做一个大分讨就行了,复杂度 \(O(n^2)\)。AC Code


DP-W Intervals Present 7.0

设 \(f(i,j)\) 表示前 \(i\) 个数,只考虑 \(r_x\le i\) 的区间 \([l_x,r_x]\) 的贡献,上一个 \(1\) 的位置在 \(j\) 的最大贡献。

这样一来我们相当于在每个区间的右端点处计算贡献。

我们发现 \(f(i,\cdot)\) 和 \(f(i-1,\cdot)\) 相比只多了一个 \(r_x=i\) 的这些区间的贡献,因此,当 \(j<i\) 时有

\[f(i,j)=f(i-1,j)+\sum_{r_x=i}[l_x\le j]\times a_x \]

当 \(i=j\) 时,我们枚举 \(i\) 再往前一个 \(1\) 的位置 \(k\),有

\[f(i,i)=\max\{f(i-1,k)|k<i\}+\sum_{r_x=i}a_x \]

我们发现,\(f(i)\) 与 \(f(i-1)\) 相比,相当于做了若干次区间加,以及一次区间最大值和单点修改。

因此可以用线段树维护 \(f(i,\cdots)\) 这一行,从上往下计算贡献即可。复杂度 \(O((n+m)\log n)\)。

AC Code


热身题到此结束,下面是稍难一些的题=w=


UVa10559 Blocks Future 8.0

有 \(n\) 个带有颜色的方块,消除一段长度为 \(x\) 的连续的相同颜色的方块可以得到 \(x^2\) 的分数。

你需要用一种最优的顺序消除所有方块,使得得分最多。\(1\le n\le 200\)。

例:\(12233321\to 12221\to 11\to \varnothing\),得分为 \(3^2+3^2+2^2=22\)。

考虑设 \(f(l,r)\) 为消除 \(l,r\) 所能得到的最大得分。

按照套路我们先考虑使用 \(f(l,k),f(k+1,r)\) 来转移 \(f(l,r)\),但这样并没有涵盖所有的操作。

我们有可能先把 \([l,k]\) 和 \([k+1,r]\) 内消到各剩下一些,然后拼起来消掉,这种操作是没有被考虑到的。

实际上这个 DP 设的就有些问题:\(12233321\) 消掉 \(333\) 后变成 \(12221\),这样的子序列是从来没有被考虑过的。

我们考虑枚举「第 \(r\) 个方块什么时候被消掉」。

设 \(p\) 是最小的满足 \([p,r]\) 内方块颜色均相等的正整数,那么有两种可能的方案:

但第二种决策仍然有些问题:我们不一定在消去 \([q+1,p-1]\) 后立刻消除 \(r\),而是有可能在右边再消去一些方块,然后一起消去。

我们发现消去 \([q+1,p-1]\) 后此时的序列变成了「一段区间最右边添上若干个和最右端颜色相等的方块」。

考虑把这种状态写进 DP:设 \(f(l,r,k)\) 为考虑区间 \([l,r]\),在最右端把 \(c_r\) 复制 \(k\) 份后得到的颜色序列,的答案。

这样一来有两种转移:

一些思考:

  • 这个状态也没有涵盖所有能得到的子序列啊,为什么就是对的?

确实没有涵盖所有可能的状态,但,这个状态涵盖了所有最优解能到达的状态

例如,对于 \(f(l,r,k)\),我们的确可能先消掉 \([l,r]\) 中间的某些方块,再来看最右端的方块。

但不管怎么样,我们总要消掉 \(r\) 和后面那 \(k\) 个同色方块。因此,「先消掉谁」其实并没有那么要紧。

相当于我们可能有两种操作方式:\(A\to B\to D\) 与 \(A\to C\to D\),我们确定了 \(A\to B\to D\) 一定不劣,因此就只需记录 \(A\to B\to D\) 就行了。

  • 为什么要先找到 \(p\) 满足 \([p,r]\) 都相等,再做进一步的转移?直接考虑 \(r\) 自己不行吗?

因为如果直接考虑 \(r\),那么将导致我们直接拆掉了 \([p,r]\) 这个连续段,考虑不到更优的状态。

一共有 \(O(n^3)\) 个状态,转移复杂度 \(O(n)\)。总的复杂度为 \(O(n^4)\)。

注意到如果用记忆化搜索实现,大多数状态实际上转移不到,足够通过 \(n=200\) 的测试点。AC Code


CF1699D Almost Triple Deletions Future 7.5

有一个长为 \(n\) 的序列 \(a\),每次操作你可以选择一个 \(i\in [1,n-1]\),满足 \(a_i\neq a_{i+1}\),然后删掉 \(a_i\) 和 \(a_{i+1}\)。

你需要把序列删到只剩下一种颜色。问最多能剩下多少个数。\(1\le n\le 5000,1\le a_i\le n\)。

例如,\(3212311\) 的答案为 \(3\),方案为 \([32]12311\to 1[23]11\to 111\),还剩 \(3\) 个数。

第一反应是枚举剩下的数是哪个,然后考虑贪心......最后场上一直没做出来orz

实际上换一种方法考虑:我们相当于要选出一个尽可能长的子序列,满足:

第二个条件等价于区间长度为偶数,且区间内不存在「绝对众数」。

略证:必要性显然,考虑充分性怎么证。

考虑归纳,若结论对 \(n=2k\) 成立,当 \(n=2(k+1)\),我们删掉出现次数最多的数与它旁边的一个元素,转化为 \(n=2k\) 的情形。显然,此时不会有出现次数 \(>k\) 的数。由归纳知结论成立。

于是就是一个简单的 DP 了:设 \(f_i\) 表示以 \(i\) 结尾的最长子序列长度,有

\[f_i=\max\{f_j+1|a_i=a_j \text{ and }[j+1,i-1] \text{ can be fully deleted}\} \]

预处理哪些区间能被删完即可。复杂度 \(O(n^2)\)。AC Code


ABC262G LIS with Stack Future 8.2

相当于选出一个最长的子序列,使得这个子序列能够通过一个栈排序。

通过思考发现,一个排列 \(a\) 能通过一个栈排序,当且仅当不存在 \(i<j<k\) 使得:\(a_j>a_i>a_k\)。

证明:

若存在 \(i<j<k\) 使得 \(a_j>a_i>a_k\),那么 \(a_i\) 最先入栈,需要在 \(a_j\) 之前出栈,但又要在 \(a_k\) 之后出栈,故此时不可能将其排序。

反之,使用归纳法:若 \(\forall k<n\),对长为 \(k\) 的排列均有结论成立,那么当 \(k=n\) 时,记 \(a_j\) 为最小的 \(j\) 满足 \(a_j>a_1\),那么 \(\forall x\ge j\) 有 \(a_x>a_1\),\(\forall 1<x<j\) 有 \(a_x<a_1\)。这表明我们可以将 \(a_1\) 先入栈,然后将 \(a[2\cdots j-1]\) 扔进去排序再出栈,将 \(a_1\) 出栈,然后将 \(a[j+1\cdots n]\) 扔进去排序再出栈。

那么我们 DP 的过程其实就是把这个证明的构造过程写进去。

我们考虑选不选 \(a_1\),如果选了 \(a_1\),我们枚举这个分界点 \(j\),现在要在 \([2,j-1]\) 中选出 \([1,a_1-1]\) 中的数,在 \([j+1,n]\) 中选出 \([a_1+1,n]\) 中的数。

那么可以设 \(\text{dp}[s][t][l][r]\) 表示 \(a[s\cdots t]\) 中选出 \([l,r]\) 内的数,最多能选多少。转移需要枚举分界点,因此总的时间复杂度为 \(O(n^5)\)。

可以发现后两维远远卡不满 \(O(n^2)\),因此完全能过。AC Code


ABC262Ex Max Limited Sequence Future 8.2

区间 \([L_i,R_i]\) 的最大值为 \(X_i\) 相当于 \(\forall L_i\le x\le R_i,A_x\le X_i\) 以及 \(\exist L_i\le x\le R_i,A_x=X_i\)。

我们维护一个 \(B_i\) 表示 \(A_i\) 可能的最大值,对每个 \((L_i,R_i,X_i)\),我们对 \([L_i,R_i]\) 区间中的每个 \(j\) 执行 \(B_j\leftarrow\min(B_j,X_i)\)。

接下来把所有 \(B_i\) 相同的 \(i\) 拎出来,那么对每个 \(X_j=B_i\) 的限制,区间中 \(=X_j\) 的数只能由这些位置来贡献。

把 \(=X_j\) 的数看成 \(1\),\(<X_j\) 的数看成 \(0\),此时问题转化为:

这个就是 CF1327F,可以做到线性。也可以用上面讲的 DP-W 的方法做到线性。

于是这题就做完了,复杂度 \(O((N+M)\log N)\)。AC Code

标签:le,题目,sum,区间,序列,选解,动态,考虑,方块
来源: https://www.cnblogs.com/YunQianQwQ/p/16655148.html