G - Paper-cutting
基本信息
题目出处 | 2019 陕西省大学生程序设计竞赛 |
队伍通过率 | 1/111 (0.9%) |
题解
容易注意到,左右对折和上下对折互不影响,因此接下来我们只考虑左右对折。
为了方便讲解,我们先考虑 \(n = 1\) 的情况,并假设只允许从左往右折。设唯一一行的元素是 \(s_1s_2\cdots s_m\),令 \(s[l:r]\) 表示子串 \(s_ls_{l + 1}\cdots s_r\)。可以发现,如果我们想要把前 \(j\) 列折到右边,需要满足 \(s[1:2j]\) 是回文串。对折之后,就相当于把字符串开头的前 \(j\) 个字符删掉。
此时读者可能会产生一个朴素的贪心策略:从第一个字符开始从左到右枚举回文串的中心,能折就折。设 \(s[1:2p]\) 是以第一个字符为开头的最短的回文串,\(s[1:2q]\) 是以第一个字符为开头的另一个回文串,接下来我们将证明,折 \(s[1:2q]\) 能到达的中间状态,折 \(s[1:2p]\) 一定能到达。
讨论 \(p\) 和 \(q\) 的关系:
-
若 \(p \le 2q\),则 \(s[1:2p]\) 和 \(s[2q-2p+1:2q]\) 是两个相同的回文串(下图红色部分),而 \(s[2p+1:2q-2p]\) 也是回文串(下图蓝色部分),因此 \(s[p+1:2q-p]\) 也是回文串(下图绿色部分)。因此如果我们先折 \(s[1:2p]\)(即删掉 \(s[1:p]\)),接下来可以再折 \(s[p+1:2q-p]\)(即删掉 \(s[p+1:q]\))。这和直接折 \(s[1:2q]\)(即删掉 \(s[1:q]\))是一样的。
-
若 \(p > 2q\),则下图蓝色部分都是相同的回文串。说明 \(s[1:2p]\) 不是以第一个字符为开头的最短回文串(蓝色回文串才是),与假设矛盾。
因此,其它所有折纸策略能到达的中间状态,一定能被“能折就折”的贪心策略到达。
那什么时候停止折纸呢?是不是直到不能再折才停止是最优的?我们的目的是最小化 \(0\) 的连通块的数量,因此我们观察一下对折前后连通块数量的变化。
- 考虑不跨过对称中心的连通块 \(s[l:r]\)(\(1 \le l \le r < p\)),则它有一个对称的连通块 \(s[2p - r:2p - l]\)。对折之后,两个连通块只剩下一个,连通块的数量减少。
- 考虑跨过对称中心的连通块 \(s[l:2p-l]\)(\(1 \le l \le p\))。对折之后它还是一个连通块,连通块数量不变。
因此折得越多,连通块数量越少。而贪心策略因为经过了其它所有折纸策略的中间状态,因此它的最终状态(折到不能再折)就是折得最多的状态,也就是最优状态。
接下来开始考虑从右往左折。此时读者可能会担心:两种折法会不会冲突?会不会从左往右折了一下,本来能从右往左折的,现在不行了?接下来将证明只要两种折法都使用“能折就折”的贪心策略,就不会冲突,因此可以分别考虑。
如下图所示,如果两种折法(下图的红色回文串和蓝色回文串)冲突了,说明其中一个回文串的对称轴位于另一个回文串内部。此时下图黑色回文串是以第一个字符为起点的更短的回文串,说明选择红色回文串不符合“能折就折”的贪心策略,与假设矛盾。
因此我们只要分别考虑四个方向,每个方向遵循“能折就折”的贪心策略,就能最小化 \(0\) 的连通块数量。回文串可以用 manacher 算法预处理,复杂度 \(\mathcal{O}(nm)\)。
参考代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
|