1、宽度优先搜索的应用李博一、 宽搜和 hash宽度优先搜索最重要的是避免重复节点的出现,判重是关键。假如每新加一个节点都与原来节点比较,相当耗时。常用的方法是用 hash 表来判重。有的题目可以把所有的状态都存下来,相当于映射。另一些就只能存下部分了,就要涉及到处理冲突的问题,一般选 hash 函数是 f(x)=x mod p(p 是一个合适的质数) ,用链表储存hash 值相同的元素。比如烦恼的设计师 (sgoi8)考虑到内存的问题,如何用最少内存建立映射是当务之急。比如魔版 (ioi1996 ) ,所有的状态是 8 的全排列,有 8!=40320 种状态,对于 n!的情况设 s1n表示一种状
2、态,令 ti表示 s1i-1中比 sI小的数的个数。那么 t 数列唯一对应0n!-1中一个数,状态表示完毕。聪明的打字员 (noi2001) ,对问题抽象后,状态只和光标的位置、光标去过的位置、第I 位上的数是原来的第几位有关。一个状态唯一对应 6!*26*6 中的一个数。向这样的问题还可以利用位压缩技术,比如补丁与错误 (ctst1999) ,对于 220 的状态进行位压缩,1byte 存 8 个 boolean 型。类似的有 数字代表 (poi99) ,用位压缩存储所有中间结果,有个值得一提的是在中间计算时没必要保存负数结果,因为假如此结果可以导致得出要求结果,则必有 a0,b0,-a+b
3、=c,那么 b-a=c 一定也是可行式且不比-a+b=c 用的 k 多。类似题目还有:阿里巴巴(poi97 ) 、位图(poi99 )二、 宽搜和图论不少和图论有关的问题可以利用宽搜解决。1找特殊点。比如:证人的可信性(poi97 ) 、署名(poi00) 。前者依次考虑每个点,利用宽搜找出此点所有同意节点。那么此点的不同意点是所有同意点的不同意点,假如发现一个点既同意又不同意则是不可靠点。时间复杂度是 o(nm)。后者主要是从 commanders 开始顺推,由于每个点访问其子节点最多 2 次,所以时间复杂度是 O(M)。这个题似乎用 dfs 比bfs 更好一些。2点合并类,这类问题既可以宽
4、搜又可以用并查集,只不过一个是静态,一个是动态而已。比如:单词方程(poi98) 、Gangs(boi2003) 、矩形(poi98) 。 矩形一题如果两个矩形相交则连边,实际上是看图是由几块组成的。 单词方程,我们可以把每一个长度为 k 变量拆成 k 个长度为 1 的变量。然后建立左右方程的对应。凡是对应的变量都应该相等。假设最后共拆出 g 个变量,则设 g+2 点,除了表示 g 个变量的点,还有表示 1 和 0 的两个点。相当与对这些点按对应合并,合并后如果 0 和 1 在一组,则无解,否则假设出了 0 和 1 外,有 m 个块,则共有 2m 组解。时间复杂度是 o(m),m 最多为 10
5、000。 Gangs ,假如不好好看题,很容易当成类似亲戚的题目,我就是这么错的:(。实际上还是可以用并查集的,可以看出朋友是可传递的,而敌人不是。所以如果 a、b 是朋友则并在一起。还可以看出来某人的敌人互为朋友,可以作个数组 t,tI表示 I 的一个敌人,如果出现(a,b)是敌人,则合并(a,tb)和 (b,ta)。是线形的算法。3抽象图求最短路,相当年猫和老鼠一题我就吃过大亏,可是并未吸取教训,这次以 poi2000Agents为例好好总结一下!给一个有向图,指定 A、B 两个点,求 AB 相遇的最短时间,其中点数 n(c,d) 变为 (a,b)-(c,b)-(c,d),即每次移动先让第
6、一个走,然后第二个再走,这样只需加 n2 个点(a,b ) ,表示第一个人已经走到 a,该在 b 的第二个人走了,而每次只能走一个人,每个点所连的边减少到 n 个,故总时间复杂度为 o(n3),较完美的解决问题。三、 宽搜和博弈目前只有一道题目:绿色游戏(poi01 )我们可以知道如果在1a中一定是 Ann 走,在a+1a+b中一定是 Billy 走。我们先不考虑圈,那么首先所有绿格是 Ann 胜的情况,然后假如格 k(k=1a )可以到一 Ann 可胜的格子去则格 k 必胜,如果 k(k=a+1a+b)所连的所有格都是 Ann 可胜,则 k 必胜。通过宽搜可以找到所有 Ann 可胜的格子。下
7、面再考虑有圈的情况,设 dI表示格 I 能到的格子数目,tI 表示格 I 能到的 Ann 不可胜的点的数目。则有如下算法:宽搜,如果绿格 I 满足(Ia) and (tI0),则只由格子 I 推出的必胜点均不满足有圈的情况。因为经过有限步游戏结束,且不必胜点一定不经过绿格而自交。现在考虑(Ia) and (tI0) 此时 Billy 走,他可以选择那个非必胜格,导致 Ann 不胜。每次宽搜并去掉这样的点,直到没有点被去掉,输出所有必胜格。四、积水(poi99)一个很不错的题目。首先有两个性质:1。水往低处流;2。边界不存水。对所有土地按高度从小到大排序,可以用基数排序在 o(nm)解决。然后对按从小到大顺序处理每块土地,如果它在边界上或者它周围有土地已经确定水的位置,则这块土地的水位是它的高度 h,并且对所有与之连通、高度小于它且没确定水位的土地标记水位 h。最后通过求水位与高度之差的和解决问题。这种方法的正确是因为对于边界的土地,水位=自身高度。对于其它土地,如果四周有土地被标记,一定比它低,则假如它可以蓄水,水一定能通过被标记的土地流出去,对于所有小于等于它且连通的土地水位一定不比它高,则其中未标记的水位最大为此土地的高度。总时间复杂度是 o(nm)