ARC119F

一个好想但不好写的做法,不需要用自动机。

容易发现,如果相邻两个位置一个是 A,一个是 B,那么从 \(0\)\(n\) 的路径一定会经过这两个位置中的一个。并且 \(0\) 到这两个位置的最短路差 \(\le 1\)(因为可以互相走)。

那就可以根据这个来 dp。设 \(f_{i,j,0/1,-1/0-1}\) 表示第 \(i-1\) 和第 \(i\) 个位置一个为 A,一个为 B。第三维表示 AB 还是 BA ,第四维表示 \(d_i=d_{i-1}+(-1/0/1)\)。转移假如说当前是 BA,那就找前面一个 B 的连续段直到一个 A,从这里转移。暴力枚举复杂度是 \(O(n^3)\) 的,因为还要枚举一个最短路长度。

考虑优化。如果上一个位置是 \(j\),那么当 \(i-j\) 比较大的时候一定不会走中间的 B 连续段,而是从两个 A 之间跳。这样的话转移就可以前缀和优化了,只需要枚举前置状态的后三维就行。 \(i-j\) 比较小的时候直接暴力枚举。我的代码为了保守一点写的是 \(i-j\le 4\) 的时候全都暴力,事实上可能可以更小。

实现上有一些细节,比如说 \(0\)\(n\) 两种颜色都可以,同时也是必经点。我的处理方法是在开头和结尾加入了两个 ?。还有一些其他 corner case 读者自行思考。

代码

https://atcoder.jp/contests/arc119/submissions/40448473

posted @ 2023-04-11 19:57  CelticOIer  阅读(10)  评论(0编辑  收藏  举报