浅谈搜索入门

         搜索是OI beginners 的必修课,也是在各类比赛中十分通用的技巧。已近三年辽宁省的NOIP 成绩为例,我们假设一名选手掌握了基本的搜索和模拟算法,那么TA的成绩将如下所示(均达到辽宁省省一线):

2010 100 + 30 + 30 + 50 = 210

2009 100 + 50 + 30 + 40 = 220

2008 100 + 100 + 30 + 10 = 240

         下面就简单谈谈各种常见的搜索并另附了一些可供练习的好题。

深度优先搜索

         深度优先搜索常用于求可行解、解的总数或者非深度最优的最优解。它可以轻松地用递归实现,当然可能也有人热衷于非递归形式。递归框架如下:

  

 


广度优先搜索

         广度优先搜索常用于求深度最优的最优解。它一般用队列来实现(如果为了节省空间可以选择取模的方式使用循环队列,如最短路的SPFA算法)。其框架如下:

 


判重问题

         搜索过程中常常遇到搜索回同一种情况的时候,就像你可以乘坐154从育才北校去南校,也可以打车过去,总之到那之后你该干嘛干嘛!如果搜索到这样一种情况,你即便再往下搜也只是重复了昨天的故事,全是无用功。这时,你就需要想办法判断你是是否回到了过去。我们通常开一个布尔数组来判重。

 

 


迭代加深搜索

         我很喜欢这个迭代加深,我认为它平衡了深搜和广搜的优缺点。它既像BFS那样高效又像DFS那样容易实现。迭代加深尤其适用于记录结点信息比较麻烦的求最深度优解的题目。它得到的第一个可行解必然最优。其框架如下:


 

 

         可能有人有疑问:你不刚说完无用功的事儿么!这么来回重新搜索不是一堆无用功么!在这里我解释一下:如果你把搜索过程想象成在一棵树上的遍历,那么如果一棵树比另一棵树多一层那么你要搜索的数据量就是翻了一番。

搜索的优化

         在做搜索题目时,我会反问自己这么几个问题,也是通常的优化思路。在做最后提到的那些题时可以体会到这些问题。

1.       以什么作为搜索对象?

2.       可否进行对解的预处理(动规、随机化……)?

3.       采用什么搜索顺序?

4.       能否忽略明显得不到合理解的结点?(可行性剪枝)

5.       能否忽略明显得不到最优解的结点?(最优化剪枝)

抓住比赛的BUG

         比赛和考试不同于联系和学习,我们不得不承认功利至上,所以要掌握比赛的技巧。

         首先,我来谈谈打表。它常常用于函数类询问,比如:n皇后解的总数、NOIP2008的火柴棒等式……实际操作就是在比赛时跑出所有输入对应的解后,建立常量数组。

         其次是卡时技巧。方法是初始化计数器为0,在每次访问结点是计数器加1即可,当达到(时限 * 9 * 10 ^ 9)时,输出当前最优解、当前解总数或者无解时的特判。

         最后说一下算法设计效率。我们期望的是得分效率高。记住,260分算法优于1100分算法!也就是说,满分算法不一定是完满算法!

推荐题目

名称

考察点

来源

提交

生日蛋糕

强力剪枝

NOI 1999

POJ 1190

木棒问题

强力剪枝+搜索顺序

ACM 中欧

POJ 1011

奶牛加密术

强力剪枝+搜索顺序

USACO

USACO 4.1.4

质数方阵

强力剪枝

IOI 94

USACO 4.3.2

靶心数独

搜索顺序

NOIP 2009

RQNOJ 521

Betsy的旅行

强力剪枝

USACO

USACO 5.4.4

拼球问题

细心搜索

CEOI 1998

POJ 1725

BLOXORZ

细心搜索

POJ 07/08/05 月赛

POJ 3322

八数码问题

康托判重

IOI 96

USACO 3.2.5

汽车问题

搜索顺序

IOI 94

POJ 1167

骑士聚会

强力剪枝+预处理

IOI 98

USACO 3.3.3

13皇后

对称判重

经典问题

USACO 1.5.4

N皇后可行解

启发式修补

经典问题

POJ 3239

十五数码问题

启发函数

经典问题

POJ 1077

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章