概述
-
强化反复是一种随机化思想。
-
具体来讲,有时题目中的限制过于复杂,无法处理或处理的复杂度不可接受。
-
此时可以考虑通过随机化地加强限制获得一个较可做的条件,然后多次反复,只要有一次恰好是答案就算成功。
-
注意,这种“加强限制”指的是将原限制简化规约到某个较强的限制上,必须保证对于所有弱限制下的可能解,都有随机化范围内占比足够大的强限制能构造出它,而非卡掉了。
例题
佛怒火莲
-
题意:
-
给定 \(n\) 个物品,每个物品有 \(v,c\) 两个参数。
-
要求从中选出任意个,使得选出的物品集中至少有 \(k\) 种不同的 \(c\)。
-
对于一个选了 \(m\) 个物品的方案,它的权重是将选出的物品按 \(v\) 升序排序后的 \(\min_{i=1}^{m-1}(v_{i+1}-v_i)\)。
-
求最大可能权重。
-
-
数据范围:
-
\(T\leqslant 5,n\leqslant 10^4\)。
-
\(c_i\leqslant n,v_i\leqslant 10^6\) 。
-
\(k\leqslant 5\)。
-
\(3s\) 时限。
-
-
显然,同种颜色的物品最多取一个。于是想到状压,但状压 \(2^n\) 显然是自寻死路。
-
先考虑压得下的话怎么办。发现没法记录上一个选的 \(v\) 和目前的 \(ans\)。于是想到二分答案 check,将物品按照 \(v\) 排序,状态转移方程中判一下 \(v\) 的差够不够大即可。
-
即:
-
状态设计:\(dp_{i,sta}\) 表示考虑了前 \(i\) 个物品,选了第 \(i\) 个物品,当前已选的物品颜色为 \(sta\),是否可行。
-
初始化:\(dp_{0,0}=1\)。
-
状态转移方程:\(dp_{i,sta}=tp_{i-1,sta}|tp_{j,sta\oplus 2^{c_i}}(v_i-v_j\geqslant now)\),其中 \(now\) 为二分的答案,\(tp\) 为 \(dp\) 的前缀或(也可认为是不要求必选 \(i\) 的伴生 DP 状态),理由显然。
-
-
然而这个 \(sta\to 2^n\)。注意到 \(k=5\)。如果 \(sta=2^5\) 该多好啊。
-
考虑染色!构建一个 \(f(c)=c'\) 的满射,\(c'\in[1,5]\)。如果最优解所需的五个物品恰好被染为了不同的颜色,则我们能 DP 出最优解。
-
则染对色的概率为 \(\dfrac{5!}{5^5}=0.0384\)。设法多染几次就好了。
-
原题后来的实现是把第二维 \(sta\) 压进
bitset
或int
的每一位,从而复杂度为 \(O(T\times times\times n\log \frac{v}{4})\),\(times\) 为随机染色次数,可以看到 \(times\approx 333\),从而正确率 \(\geqslant 99.99\%\)。
CF1310D Tourism
-
题意:\(n\) 点 \(m\) 边有边权有向图,无自环重边,求一个含 \(1\) 的恰有 \(K\) 条边的最小环,且环上不存在任意奇环。
-
数据范围:\(n\leqslant 80,K\leqslant 10,3s\) 时限。
-
不存在奇环很难整的。我会染色!
-
将原图随机赋黑白色。不妨钦定 \(1\) 为白色,则还有至多 \(k-1\) 个点,染对色的概率为 \(\dfrac{1}{2^{k-1}}\)。染完之后直接跑 Bellman-Ford,只许走交替颜色,复杂度 \(O(n^2\times k)\),正确率 \(99.98\%\)。
HDU6664
-
题意:给定一张 \(n\) 点 \(m\) 边带边权无向图,求包括 \(k\) 个点的最长(简单)路径长度。路径起点任选。
-
数据范围:
-
\(T\leqslant 35\)。
-
\(n,m\leqslant 10^4\)。
-
\(2 \leqslant k\leqslant 6\)。
-
\(\max(n,m)\geqslant 100\) 的测试点不超过 \(5\) 个。
-
-
我会染色...考虑染六色,然后规定从 \(1\) 出发走到 \(6\),跑全源最长路跑六步?额好像不用,每条边肯定对应一种颜色转换,\(O(m)\) 就可以。
-
\(O(T\times times\times m)\)。单轮正确率下界为 \(\dfrac{1}{6^6}\)。
-
不行,有点低,全放 \(m=100\),\(times=6^6\) 就要 \(1.6\times 10^8\) 了,此时还有 \(35\%\) 的错误率。
-
换个思路跑状压:
-
状态设计:\(dp_{i,sta}\) 表示当前在 \(i\),已经有 \(sta\) 的颜色的最大路径长度。嗯显然可以分层转移(加一个走了几步),空间开销打一点但是常数小一点。
-
初始化:\(dp_{i,2^{c_i}}=0\)。
-
递推转移:\(dp_{i,sta}\to dp_{j,sta|2^{c_j}}(sta\And 2^{c_j}=0)\),转移系数为 \(e_{i,j}\)。
-
-
正确率上升到 \(\dfrac{6!}{6^6}\),单轮复杂度上升到 \(O(n\times k\times sta)\)。算下来 \(times=74\),仍有 \(31\%\) 的错误率...不可做吗?
-
错了,没有那个 \(k\) 的复杂度!没有外层枚举 \(k\) 的必要,直接从小往大枚举 \(sta\),一定没有后效性,不信可以连边 toposort 试试。于是复杂度实际上是 \(O(m\times sta)\)。
-
于是将小数据转化成大数据,估算得 \(times=20\),寄了啊。
-
啊其实这个时候我们可以考虑调大 \(times\)。上面那个 DP 的复杂度分析是溢出的,实践中 \(times\) 每 \(+100\),错误率降低一个数量级。
-
为什么调大不会 T?本题 \(15s\) 时限。(来人,把这个不看题的给我叉出去!)