USACO23DEC Pt T3

发布时间 2024-01-04 21:38:15作者: Harry27182

首先要把 A 和 B 分别按顺序排序,然后有一个显然的思路是记录 $dp_{i,j,k,l,0/1,0/1}$ 表示 A 做到 $i$,B 做到 $j$,当前时刻是 $a_k+l\times T$,是 $a_k$ 还是 $b_k$,上一个走的 A 还是 B 的最小答案,转移比较简单,复杂度 $O(n^4)$。

然后发现 $l$ 这一维一定是越小越优,所以可以去掉这一维并记录进 dp 值,时间复杂度 $O(n^3)$。

发现我们状态已经达到了 $O(n^3)$ 级别,想要优化必须再去掉一维,显然 $i$ 和 $j$ 都是不能去掉的,所以考虑去掉 $k$ 这一维,更改状态 $f_{i,j}$ 表示先走 A,并且这一位上的 A 是满足发车时间和 $a_i$ 相同的。类似地设计 $g_{i,j}$ 状态,这样就把状态压到了 $O(n^2)$ 级别。考虑如何转移。

下面以 $f$ 为例说明转移。首先有 $f_{i,j}\rightarrow f_{i+1,j}$,不需要代价。然后如果满足 $b_{j+1}\geq a_i+T$,那么可以进行一个 $f_{i,j}\rightarrow g_{i,j+1}$,否则一定是在 AB 交替走一段长度为 $T$ 的时间,把能启动的全部启动,这样显然是不劣于留一些不走的。所以可以模拟这个过程,最多交换 $O(n)$ 次就会到达终点,所以转移的复杂度是 $O(n)$ 的,总的复杂度仍然是 $O(n^3)$,但是显然更有前途一些。

发现这样其实没什么前途,刷表法并不好优化,即使能优化代码实现上也并不简单,填表法发现没法处理出来每个点是从哪来的,这样就陷入了瓶颈。我们考虑正难则反,把状态改为当前已经昨晚前面一部分,还需要多少的代价才能解决问题。这样做的好处是,固定前面状态处理后面状态的过程,前面是刷表现在就变成了填表,而填表一般是比刷表好优化的。而从后面状态去处理前面状态的过程,由于映射是一对多的不确定性,并没有优化前途。这样我们就把有优化前途的一部分变成了填表,这一部分的映射是一对一的。考虑如何利用这个映射的唯一性。

发现如果 $f_{i,j}$ 往后走的过程,下面的位置其实是与 $j$ 无关的,一定是走到最后一位满足 $b_k<a_i+T$ 的 $k$,$g$ 的转移同理。所以这就意味着,转移除了第一段,$i$ 相同 $j$ 不同时是一样的,考虑预处理出来 $k$ 对应的最小值,对于其他的 $j<k$ 只需要加上前面一节前缀和即可。由于只需要预处理 $O(n)$ 个位置,所以这部分复杂度就是 $O(n^2)$ 的了,而转移也被优化为了 $O(1)$,所以总的复杂度就是 $O(n^2)$。

回顾这题,做了一个变 $3d/0d$ 为 $2d/1d$,让算法有了优化的可能性。然后又考虑到映射的唯一性,选择将状态反向,从而能把映射唯一的情况对应较为简单的填表法的操作。所以,我个人认为这是一道非常有代表性的 dp 优化好题。