csps 线性dp

发布时间 2023-10-02 21:07:49作者: carp_oier

合唱队形

正反分别求一遍最长上升子序列,然后枚举中间的最高点,计算出来队列里面的最多人,然后就可以知道需要出列的最少人。


过河

tips:两个互质的数字 p,q,他们所不能拼出来的最小的数字是 \((p-1)(q-1) - 1\)

我们可以用 \(f[i]\) 表示经过长度 i 之间,我们所踩石头的最小数量。

但是整个区间的长度过于长(1e9)我们没有办法放在下标里面,我们就可以用上面的 tip 来解决问题。我们可以知道,如果两个石子之间的距离超过了 100 (更准确地说是 91) 那么我们就可以把他给缩放成 100。这样子就解决了这个长度过长的问题。
转移方程:

\[f[i] \gets \min{f[i-t],f[i-t + 1], ..., f[i-s]} + w[i] \]


传纸条

题目相当于是让我们跑两次求路径和的最大值。这样的话,我们可以考虑同时跑这两个,对于这个图的一个转态表示,首先想到的应该是思维分别存储 x1, y1, x2, y2 但是我们可以通过经验得到,我们对于同一步来说,x 与 y 的和是一个定值,所以我们就可以简化成三维,用 \(f[k][x1][x2]\) 来表示。

而且我们不难看出这个路线是不能有交叉的(但是可以有交点)。

我们在计算转移的时候从四个方向转移就行了,从上面过来,从左面过来。组合。四种转移。其中取到的格子中的数,要注意判断是不是在同一个位置,以免重复计算。

对于 x1 和 x2 的循环边界要注意是 \(\max(1, k-m)\) 不可能总共 m 列然后走出框去


乌龟棋

题目告诉了我们使用的卡片有四种,那我们不妨就按照这四种卡片的使用数量来表示我们所能取到的数字的最大值。即一个四维状态 \(f[A][B][C][D]\) 分别表示每个卡片分别用了这么多卡片之后我们所能获得的分数的最大值。

我们也只需要枚举每个卡片 A,B,C,D 的使用个数就行了。

\[f[A][B][C][D] \gets \max{f[A-1][B][C][D], f[A][B-1][C][D], f[A][B][C-1][D], f[A][B][C][D-1]} + w[1 + A + 2 * B + 3 * C + 4 * D] \]


子串

我们用 \(f[i][j][k]\) 表示 我们已经用 A 中前 i 个字母表示了 B 中的 前 j 个字母,且已经分成了 k 段的方案数。

但是我们的空间复杂度会炸掉,就要考虑空间优化。

空间优化的方法:

  • 如果只跟上一步有关,可以让第一维变成 2 使用滚动数组增加空间效率。
  • 如果第一维只跟上一层有关,之后的几维都是从它之前的状态转移过来,我们就可以省去第一维,然后将第二维用倒序的方法进行更新。

先分析三维的:对于一个已经有了长度为 t 的一个串 A 我们首先可以写出来转移方程。

\[f[i][j][k] \gets f[i-1][j-1][k-1] + f[i-2][j-2][k-1] \dots f[i-t][j-t][k-1] \]

然后我们再列出 i - 2 的情况,发现有很大一部分是会被重复计算的。
所以我们可以用前缀和来维护这个值。

\[f[i][j][k] \gets f[i-1][j-1][k-1] + \sum_{t=1}^{j}f[i-t][j-t][k-1] \]

我们可以用前缀和来提前处理出来后面这个求和

\[sum[i][j][k] \gets \sum_{t=1}^{j}f[i-t][j-t][k-1] \]

然后我们的式子就变成了

\[f[i][j][k] \gets f[i-1][j][k] + sum[i][j][k] \]

我们再用上叙的方法,就可以切掉这题。


Emiya家今天的饭

状态表示:只用前 i 种烹饪方法,做了 j 道菜的方案数

状态转移:$$f[i][j] = f[i][j-1] + f[i-1][j-1] * \sum_{i=1}^{m} a[i]$$