7.3 搜索

搜索既是一种算法也是一种思想,OI中有许多东西都是建立在搜索的基础之上进行优化的。

简而言之,搜索就是一项项地将所有可能性遍历,寻找正确答案。

最基础的搜索有深度优先搜索(DFS)与广度优先搜索(BFS)。

二者在本质上没有区别,只是搜索顺序不同。

DFS是一个一个答案地搜,与我们小学数学中做最基础的枚举题时惯用的顺序是一致的。

而BFS是像灌水一样一层层地搜,最后一步将所有答案同时求出。

虽然二者在本质上没有区别,但是在应对不同情况中的实际表现是不一样的。

在朴素的搜索之上,可以加上一些优化,通常我们称之为“剪枝”。(从可能答案组成的树中减去确认不能的)

比如下面这一道题剪枝与不剪枝就有着一定的差异。

棋盘问题

Problem
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。
要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放kk个棋子的所有可行的摆放方案C。

Input Data
输入含有多组测试数据:
每组数据的第一行是两个正整数n,k,用一个空格隔开,表示了将在一个n∗n的矩阵内描述棋盘,以及摆放棋子的数目。 (n≤8),(k≤n)
当为−1 −1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中“#”表示棋盘区域,“.”表示空白区域(数据保证不出现多余的空白行或者空白列)。

Output Data
对于每一组数据,给出一行输出,输出摆放的方案数目C(数据保证C < 2^{31})。

最基本的想法是一个个棋子地枚举,然后最后判断是否成立。

但是这样要枚举的可能性太多,因此考虑剪枝。

当我们准备放下一枚棋子的时候,可以直接判断是否合法——因为每一行每一列最多能有一枚棋子。实现上维护两个数组表示行列的占用情况即可。

本题还有一个很坑的细节,即“#”是可以放置棋子的区域而“.”是不能放置棋子的区域,这与一般的题目是相反的。

很大一部分搜索题的数据范围都十分明显地暗示着算法,但是也有少量搜索题范围不那么明显,比如下面这道:

Hexadecimal's Numbers

Problem
给定一个整数n(1~1e9),求在1到n范围内,有多少个整数是由0和1两种数字组成的。

Input Data
一行一个整数n。

Output Data
一行一个整数,表示符合要求的整数的个数。

第一眼看上去数据范围十分不可做,酷似O1题(然而没有结论)。

但是仔细思考,由于符合要求的整数每个数位上不是0就是1,最多也只有512种可能性,所以可以直接枚举。

最后在检验的时候需要注意0001和00000001是一样的,不要重复计算。

猜你喜欢

转载自www.cnblogs.com/ilverene/p/11129114.html
7.3