排除等效冗余

概述

排除等效冗余,是一个范围很广的概念,大到算法思想的设计,小到对题目的转化。但不可否认,这种思想在做题中经常出现。往往出题人整选手,会将题目出的复杂一点。事实上,很多条件都是没用的或者可以被简单代替的,但若不排除这些冗余条件,将给做题带来较大影响。所以,这种思想方法必须掌握。

本文将从排除等效冗余的角度对每道例题进行重点剖析,至于其他过程,可以详见博客。

对无用状态的去除

感觉很熟悉,对吧?没错,在学习搜索剪枝时,我们常用到这种优化思想,分别称为最优性剪枝可行性剪枝

最优性剪枝,即从最优化的角度考虑剪枝:如果当前计算的答案已经没有之前的答案优,再计算下去一定不会更优,可以直接终止这次的搜索,考虑其他计算。

这是在搜索剪枝中的应用。其实在平时做题中也经常出现,比如:有 \(a\)\(b\) 两种选择,其中 \(a\) 无论从自身对答案的贡献,还是帮助其他值对答案的贡献来看,都是最优的,那么我们可以只保留 \(a\) 而将 \(b\) 去掉,毕竟 \(b\) 明显更劣。

这和单调队列也很像,如果一个值更优还更靠前(前还是后依题目而定),那么必然将其他值踢掉,保留当前值

我们来看几道关于最优性优化的题目(不包括单调队列和搜索)。

最优性优化

T1


\(n\) 块白色或黑色的石头排成一排,第 \(i\) 块石头的重量为 \(w_i\) 。你每次可以取走一块石头。如果这块石头不在最左侧或最右侧,并且和它相邻的两块石头的颜色均与它自己的颜色不同,你可以获得 \(w_i\) 分;否则,你不得分。两块石头是相邻的当且仅当它们之间没有还没被移走的石头。你要求出你的最大得分。

可以发现,对于一段连续的形如 WWWW 这样的一堆颜色相同石子,我们只保留其中权值最大的一定是最优的,我们考虑从石子对别人的贡献本身对答案的贡献进行分析。

由题知,只有相邻的石子与自己颜色不相等,取的时候才能得分。所以从对答案的贡献来看,一堆石子(数量记作 \(k\))一定是先取走 \(k-1\) 个不得分的,再取走一个得分的,显然我们要让最后一个能得分的权值尽量大,即最后取走的是这\(k\)个石子中的最大值。

那么,只保留一个石头,会对相邻其他颜色石头的选取造成影响吗?

显然不会,对于 BWWWWBBWB 来讲,可以先选取两边的B,最后选取中间的W,所以只保留一个不会对其他答案的选取造成影响。

经过一波简单的转化,将字符串转化为了WBWBWBWB这种颜色交替的字符串,然后简单分析性质就可以做。

T2


给定一个长为\(n\)的正整数序列\(a_1,a_2,…,a_n\)

\(a\) 的一个长度为 \(k\) 的子序列 \(b_1,b_2…,b_k\),并且最小化

\(value=max(b_1+b_2,b_2+b_3,…,b_{k−1}+b_k,b_k+b_1)\)

求出 \(value\) 的最小值。

幼儿园都看的出来的二分答案。。。

我们考虑如何进行check

对于相邻的 \(a_i,a_{i+1}\) 而言,若 \(a_i+a_{i+1}>mid\),且 \(a_i<a_{i+1}\),我们应该选择那个进 \(b\) 呢?

从对合法序列长度的贡献来看,选择 \(a_i\) 和选择 \(a_{i+1}\) 的贡献都是 \(1\) ,我们考虑两个选择对\(a\)数组其他位置的选择的影响。

由贪心可得,如果选择 \(a_i\),那么后面更容易满足 \(a_i+a_k\le mid\) 的条件,所以我们可以得出一个结论,选择 \(a_i\) 一定不比选择 \(a_{i+1}\) 劣。

由此可以得出算法:按照上述思路不断合并相邻不合法的两项,可以用链表或者双端队列实现。我用的是双端队列。


可行性优化

其实可行性优化不仅仅表现为对代码的优化,也表现为对算法时间复杂度的分析,往往确认时间复杂度不是建容易的事(尤其是记忆化搜索这种玄学算法)。

来看几道题。

T1

现在有一个 \(n×m\) 的格子大小的木板,大王想用 \(1×2\) 的多米诺骨牌把格子填满。大王不满足于普通的填法,大王还想让每个格点都不能被 \(4\) 个多米诺骨牌顶点覆盖。

问有多少种填的方式。\(1\le n,m \le 10^7\)

乍一看非常复杂。二维计数题,\(1\le n\times m\le 10^{14}\) ,显然不能用正常的 \(dp\) 思路。注意,在山穷水尽之时,我们就要考虑一个问题:是否存在无用的状态呢?

通过手模我们可以算出,合法的矩形只有行数为 \(n\) 的,两个行数不为 \(n\) 的矩形拼在一起是不合法的。这样我们就将二维问题转化为一维问题。然后进行简单的递推即可。

T2

给定参数 \(b_1\sim b_m\),以及 \(a_1\sim a_n\),进行 \(m\) 次操作,第 \(i\) 次操作可以选择保留 \(b_i\) 的倍数或者去掉 \(b_i\) 的倍数。先手希望操作完权值和最小,后手希望操作完权值和最大。问最终的权值。

\(1\le n\le 2\times 10^4,1\le m\le 2\times 10^5.\)

乍一看,题目很难,用正常的 \(dp\) 或者贪心都不太好搞,因为我们很难不维护当前的数集 \(a\) ,但是维护数集 \(a\) 意味着空间时间绝对爆炸(毕竟 \(n\le 2\times 10^4\)),对于这种看上去不可做题,一般而言,要么是答案很少,要么是算到一定程度答案是恒定的

考虑暴力怎么做,按照博弈论的套路,暴力的枚举每一步的决策,设 \(dfs(i,s)\) 表示现在在进行第 \(i\) 轮,数集是 \(s\) ,算出的权值。如果是先手,就走向对手取到最小值的路径;反之亦然。

那我们考虑,假设是 \(b_i\) 倍数的有 \(num_1\) 个,不是的有 \(num_2\) 个, 如果取多的那边,那么每次数集的大小就会减半,只需进行 \(\log n\) 次操作就可以将数集取空,那么由于一个人想让结果变大,另一个人相反,于是若先手取了减少后少的那一边,后手就会取减少后多的那一边,整理一下,最多经过 \(2\log n\) 次操作,就能将数集取空,答案为 \(0\).

所以在感觉状压不行,贪心不行,\(dfs\) 爆搜也不行的情况下,就要坚信出题人在出 诈 骗 题 。

T3

折线

洛谷月赛的题,想了 \(10\) 分钟发现不对路,答案只会是 \(2,3,4\) 其中一个,\(2\) 的情况很好判断,所以只需要判断 \(3\) 的情况即可。可以很套路的枚举中间折点,也就是 \(3\) 个折点中唯一一个不在坐标轴上的那个。然后统计对应矩形内的点的数量即可,是个二维偏序问题,树状数组即可。直接枚举容易超时,用二分即可。

T4

Cuber QQ 有一个长度为 \(n\) 的数列 \(a_1,a_2,⋯,a_n\),其中有一些位置 Cuber QQ 已经填上了数。

对于空着的位置 Cuber QQ 想考验一下 Little Fang,他希望 Little Fang 在空白位置填上一些数后,使得这个数列的任意连续子序列的和都是质数,也就是说,

\[\forall l,r,1\le l\le r\le n,(\sum_{i=l}^ra_i)是质数 \]

\(Xiejiadong\) 出的题,这个出题人最喜欢用诈骗题阴人,你看,又来了。。。

回归正题,发现与质数有关的算法其实不多,要使得任意区间内的数字和都为质数,\(dp\) 和贪心看上去都不好做,我们考虑会不会出现无解等情况。

首先,每个位置上必须是质数(长度为 \(1\) 的区间),接着研究相邻的情况,发现,如果两个质数都是奇数,那么加一起是偶数,不满足题目条件,所以要用到唯一的偶质数 \(2\),并且在序列中一定是交替出现的,像这样子(设 \(p\) 是奇质数):

\[p_1\;\;2\;\;p_2\;\;2\;\;p_3... \]

接着考虑长度为 \(3\) 的序列,发现如果是 “奇质数 2 奇质数” 这样的排布,加起来还是会得到偶数(不合法),所以唯一合法的排列只有 “2 奇质数 2”。

分析到这里不能发现,长度为 \(4\) 的序列怎么搞都不合法,因为只能出现 “2 奇质数 2 奇质数” 这样的的排列,加一起是偶数,不合法。

所以长度为 \(4\) 的序列没有合法序列,那么长度是 \(5,6,7...\) 的序列也自然不存在合法序列。

所以我们只需要考虑长度\(\le3\) 的情况,是不是简单许多。。。

T5

给定一棵 \(n\) 个节点的树,顶点编号为 \(1,2,...,n\),你需要给每个顶点设置一个标号 \(c_i\) 满足:

  • \(1\le c_i \le n\)
  • \(c_i\ne c_j\;(i\ne j)\)
  • \(|c_i-c_j|\le 2\)\(i,j\) 树上相邻)

求方案数。

可以考虑暴力的 \(dp\),设 \(f_{i,p_1,p_2,S}\) 表示当前填了 \(1\sim i\) 的标号,其中 \(i\) 填在点 \(p_1\)\(i-1\) 填在点 \(p_2\),填过的点的集合是 \(S\) 的方案数。

枚举标号 \(i+1\) 将要填的位置,记作 \(p_3\),设新集合是 \(T\),那么有如下转移:

\[f_{i+1,p_2,p_3,T}\Leftarrow f_{i,p1,p2,S} \]

直接暴力的 \(dp\) 无疑会超时,考虑优化,采用排除无用状态的方式。

考虑这样的问题,如果 \(1\sim i+1\) 的标号都填完了,我们能否确定当前填的方案是否合法呢?

显然可以,对于 \(i-1\) 而言,满足 \(|c_i-c_j\le 2|\) 并且 \(i,j\) 树上相邻的无非在 \([i-3,i+1]\) 内,由于我们按照标号从小到大的顺序填,若填到 \(i+1\),对于 \(i-1\) 填在的位置(记作 \(p\))来讲,与 \(p\) 相邻的点还有没填的,即使后面填上也不可能合法,所以我们得到如下结论:

填完 \(1\sim i+1\),与 \(i-1\) 位置相邻的必须全部填上

加上这个剪枝以及记忆化搜索,就可以 A 了。

为什么?

首先,每个点的度数一定不超过 \(4\),超过 \(4\) 显然无解,接着,我们将 \(f_{i,p_1,p_2,S}\) 中的 \(p_1,p_2\) 点删除,最多得到 \(7\) 棵树,每棵树要么全部被填,要么全部不被填。如果出现落单的,在后面的填写中也不可能被填,所以合法的状态最多有 \(2^7\) 种,设树的个数是 \(c\)

那么时间复杂度是 \(O(n\times 2^c)\)

posted @ 2022-11-22 09:32  2017BeiJiang  阅读(84)  评论(0编辑  收藏  举报