Loading

题解:CF1767E Algebra Flash

可以在 cnblogs 中阅读。

\(m \le 40\) 的数据范围提示让我们往颜色种类上考虑。

由题每次可以跳 \(1\)\(2\) 格,即存在一条从 \(1\)\(n\) 的路径的充要条件是不存在两个相邻的未激活格。换句话说,对任意两个相邻的格子都必须选择至少一个激活。

任意两个,至少一个,这样的条件使我们联想到最小权点覆盖,我们在 \(1\) 号和 \(n\) 号连自环,其他点相邻的颜色连边,问题转化为求这个图的最小点覆盖。

一个经典结论是最大权独立集 + 最小权点覆盖 = 点权和。最大权独立集可以用记忆化搜索的方式实现。

具体地,设 \(f_S\) 表示集合 \(S\) 的最大权独立集,则有转移:

\[f_S = \max \left\{ f_{S- \left\{ p \right\} },f_{S- \left\{ p \right\} -edge(p)} \right\} \]

其中 \(p\) 表示集合中一个点,\(edge(p)\) 表示与 \(p\) 有连边的点集。

但是 \(m \le 40\),怎么开的下?用 std::map 等工具可以动态开记忆化数组,而状态数的转移满足 \(G(m) \le G(m-1)+G(m-2)\),最劣情况下是一个斐波那契数列,也就是说 \(G(m) \le O(1.618^m)\)\(m=40\) 时在 \(2 \times 10^8\) 的级别,而实际上远远跑不满,时间空间都可以接受。

code,使用 __pbds::gp_hash_table 可以跑得更快。

实际上还有一种做法,就是对高 \(20\) 位爆搜,低 \(20\) 位记忆化,这样做保证了复杂度是 \(O(n+2^ \frac{m}{2})\),而且避免了开 map 等时空消耗大的操作,实测也跑得更快。

code

posted @ 2024-09-13 09:40  tai_chi  阅读(1)  评论(0编辑  收藏  举报