搜索算法讲解
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
•
• void Dfs ( int x, int y ) {
• int i;
• if ( map[x][y] == '@' && flag[x][y] == false ) {
•
flag[x][y] = true;
•
for ( i = 0 ; i < 8; i++ ) {
•
int tx = x + move_x[i];
•
for ( j = 0 ; j < n ; j++ ) {
•
cin >> map[i][j];
•
}
•
}
•
for ( i = 0 ; i < m ; i++ ) {
•
for ( j = 0 ; j < n; j++ ) {
•
if ( map[i][j] == '@' && flag[i][j] == false ) {
– DBFS算法从两个方向以广度优先的顺序同时扩展,一个是从起 始节点开始扩展,另一个是从目的节点扩展,直到一个扩展队 列中出现另外一个队列中已经扩展的节点,也就相当于两个扩 展方向出现了交点,那么可以认为找到了一条路径。
• 比较
– DBFS算法相对于BFS算法来说,由于采用了从两个根开始扩展 的方式,搜索树的宽度得到了明显的减少,所以在算法的时间 复杂度和空间复杂度上都有优势!
•
2) 否则扩展(expand())队列q2 (即tail[0]-head[0] >= tail[1]-head[1]时)
• 3. 如果队列q1未空,循环扩展(expand())q1直到为空
• 4. 如果队列q2未空,循环扩展(expand())q2直到为空
•}
双向广度优先搜索
• 算法流程:
• 二、扩展函数: • int expand(i) //其中i为队列的编号(表示q0或者q1)
广度优先搜索
• 优点
– 目标节点如果存在,用广度优先搜索算法总可 以找到该目标节点,而且是最小(即最短路径) 的节点
• 缺点
– 当目标节点距离初始节点较远时,会产生许多 无用的节点,搜索效率低
双向广度优先搜索(DBFS)
• DBFS算法是对BFS算法的一种扩展。
– BFS算法从起始节点以广度优先的顺序不断扩展,直到遇到目 的节点
广度
优先
搜索
算法
下 举例
234
18
765
右
123 784
65
12 3 84 7 65
目标
深度优先搜索
• 用堆栈存储 • 当前结点为下一次扩展结点的父结点
0
1
2
3
45 6
void DFS(int curNode,int curDepth){ if(curNode == Target ) return ; if(curEdpth > MaxDepth)return; for(int i=0;i<n;++i){ int newNode = Expend(curNode,i); DFS(newNode,++curDepth); } return;
双向广度优先搜索
• 算法流程:
• 一、主控函数:
• void solve()
•{
• 1. 将起始节点放入队列q1,将目的节点放入队列q2
• 2. 当 两个队列都未空时,作如下循环
•
1) 如果队列q1里的未处理节点比q2中的少(即tail[0]-head[0] < tail[1]-
head[1]),则扩展(expand())队列q1
搜索
人肉搜索
度娘
文件查找
爬虫
什么是搜索算法呢?
搜索算法是利用计算机的高性能来有目的地穷举 一个问题的部分或所有的可能情况,从而求出问题 的解的一种方法。
搜索过程实际上是根据初始条件和扩展规则构造 一棵解答树并寻找符合目标状态的节点的过程。
what
广度优先搜索
• 广度优先搜索:从初始状态开始,通过规 则来生成第一层结点,同时检查生成结点中 是否有目标结点.若没有则生成下一层接点, 并检查是否有目标结点…
•
Dfs ( i, j);
•
sum++;
•
}
•
}
•
}
•
cout << sum << endl;
•}
• return 0;
深度优先搜索
• 优点
– 空间需求少,深度优先搜索的存储要求是深度 约束的线性函数
• 问题
– 可能搜索到错误的路径上,在无限空间中可能 陷入无限的搜索
– 最初搜索到的结果不一定是最优的
deposits. GeoSurvComp works with one large rectangular region of land at a time, and creates a grid that divides the land into numerous square plots. It then analyzes each plot separately, using sensing equipment to determine whether or not the plot contains oil. A plot containing oil is called a pocket. If two pockets are adjacent, then they are part of the same oil deposit. Oil deposits can be quite large and may contain numerous pockets. Your job is to determine how many different oil deposits are contained in a grid. • Input • The input contains one or more grids. Each grid begins with a line containing m and n, the number of rows and columns in the grid, separated by a single space. If m = 0 it signals the end of the input; otherwise 1 <= m <= 100 and 1 <= n <= 100. Following this are m lines of n characters each (not counting the end-of-line characters). Each character corresponds to one plot, and is either `*', representing the absence of oil, or `@', representing an oil pocket. • Output • are adjacent horizontally, vertically, or diagonally. An oil deposit will not contain more than 100 pockets.
83 214 765
283 714
65
28 143 765
283 145 76
123 784
65
4 283
层
64
175
283 16 754
83 214 765
283 714 65
28 143 765
283 145 76
深度 优先 搜索 算法 举例
12 Hale Waihona Puke Baidu 84 7 65
目标
• 1241 • Description • The GeoSurvComp geologic survey company is responsible for detecting underground oil
• using namespace std;
•
• const int MAX = 100;
• int m,n;
• char map[MAX][MAX];
• bool flag[MAX][MAX];
• int move_x[8] = {-1, 0, 1, 1, 1, 0, -1,-1};
• int move_y[8] = {-1, -1, -1, 0, 1, 1, 1, 0};
•}
• int main ()
•{
• while ( cin >> m >> n && m!=0 && n!= 0 ) {
•
memset ( flag, false, sizeof ( flag ) );
•
int i,j,sum = 0;
•
for ( i = 0 ; i < m ; i++ ) {
• 给定 3 X 3 的矩阵如下: 234
• 技巧: 每次扩展结点总是选择结点比较少的那边进行下次 搜索,并不是机械的两边交替。
双向广度优先搜索
• 双向广度优先算法编程的基本框架如下: • 数据结构: Queue q1, q2; //两个队列分别用于两个方向的
扩展(注意在一般的广度优先算法中,只 需要一个队列) int head[2], tail[2]; //两个队列的头指针和尾指 针
广度优先搜索
• 采用队列存储 • 每次扩展出当前结点的所有子结点
0
1
2
3
45 6
广度优先搜索
void BFS(int curNode,int curDepth){ while(front < rear) { ++front; for(i = 0; i < m; i++) { newNode = Expend(q[front].node) if(!Exist(newNode)) { q[rear++].node = newnode; } if(newNode == target) return ; } } return;
1
23
184
2下
765
左3
右
4
1层
283 14
23 184
23 184
5下
283
765 右
左
2
8
63
765
7
283
下 765
8
123
2层
164
14
14
84
左
75
右
765
765
上
下上
765
下下
283
3层 1 6 4
283 164
83 214
283 714
28 143
283 145
75
75
765
65 765 76
• Sample Input • 11 •* • 35 • *@*@* • **@** • *@*@* • 18 • @@****@* • 55 • ****@ • *@@*@ • *@**@ • @@@*@ • @@**@ • 00 • Sample Output •0 •1 •2 •2
• 题目的意思就是在给出的图中@代表有石油,*代表没有石油,而在一个有石油的地方它的 周围8个方向的地方如果也有石油,那么这2块石油是属于一块的,给出图,问图中有几块石 油田.
• 若图为下图: • @@ •@ • @@ • 是连成一块的,所以图中只有一个油田. • 解题方法:
• 采用深度优先搜索策略,对给出的图中一旦出现一个@则对其8个方向进行搜索,并 对搜索过的@标记,直到一次搜索结束则油田总数加一,最后的总数即为所求的石油
。 的方块数
• #include <iostream>
}
搜索算法举例:八数码难题
• 在3×3的方格棋盘上,分别放置了标有数字1、2、 3、4、5、6、7和8的八个棋子
– 空出一个位置使棋子可以移动,形成不同的局面
S0 2
3
初始 1 8 4
状态 7 6 5
1 2 3 Sg
8
4 目标
7 6 5 状态
– 问题 要使棋盘进入某种预定局面应如何移动棋子
规则:空格上下左右 0层
}
• 函数的返回值可以根据具体的情况来设定
0 规则:空格上下左右
23 1 184
层
下
2
765
左 12
右
283
23
23
1
14
184
184
层
765
765
765
3
6
9
13
2 层
283 164 75
283 14
765
283 14 765
123 84
765
4
5
7
8
10
11
283
3 164 层 75
283 164 75
•{
•
取队列qi的头结点H
•
对头节点H的每一个相邻节点adj,作如下循环
•
1 如果adj已经在队列qi之前的某个位置出现,则抛弃节点adj
•
2 如果adj在队列qi中不存在
•
1) 将adj放入队列qi
•
2) 如果adj 在队列(q(1-i)),即在另外一个队列中出现,输出 找到路径
•}
双向宽度优先搜索求解8数码问题
•
int ty = y + move_y[i];
•
if ( tx >= 0 && ty >= 0 && tx < m && ty < n && map[tx][ty] == '@' && flag [tx][ty] == false ) {
•
Dfs ( tx,ty );
•
}
•
}
•
return ;
•}