算法笔记——搜索初步

        把这几天学的搜索做一个初步总结。
       一、 深度优先搜索(DFS):从起点出发,走过的点要做标记,发现有没走过的点,就随意挑一个往前走,走不动了就回退。不能走已经走过的点(需要判重)。
       举几个栗子:
       1.判断从V出发是否能走到终点:

bool Dfs(V) {
if( V 为终点)
return true;
if( V 为旧点)
return false;
将V标记为旧点;
对和V相邻的每个节点U {
if( Dfs(U) == true)
return true;
}
return false;
}

判断从v出发是否能走到终点时,返回值有意义。

因为有回溯的过程,所以会把k出发能走到的点都走一遍。

2.判断从v出发是否能走到终点,如果能,要记录路径。

bool Dfs(V) {
if( V为终点) {
path[depth] = V;
return true;
}
if( V 为旧点)
return false;
将V标记为旧点;
path[depth]=V;
++depth;
对和V相邻的每个节点U {
if( Dfs(U) == true)
return true;
}
--depth;
return false;
}

--depth的过程就是回溯的过程。

3.在图中寻找最优(步数最少路径)

void Dfs(V) {
if( V为终点) {
path[depth] = V;
if( depth < minSteps ) {
minSteps = depth;
拷贝path到bestPath;
}
return;
}
if( V 为旧点) return;
if( depth >= minSteps ) return ; //最优性剪枝
将V标记为旧点;
path[depth]=V;
++depth;
对和V相邻的每个节点U {
Dfs(U);
}
--depth;
将V恢复为新点
}

求最优路时,要把走过的不同的路保留下来。

为什么将v恢复为新点:为了之后的兄弟可能会绕回v。

找最优路时返回值无意义。

图的存储方式对遍历v的相邻节点u过程的影响:

邻接矩阵遍历:O(n²)

邻接表遍历:O(n+e)

稀疏图用邻接表存储效率更高。

剪枝:最优性剪枝,可行性剪枝。(待更新)

 

 二、 广度优先搜索(BFS):依层次顺序,从小到大扩展节点。把层次低的点全部扩展出来后,才会扩展层次高的点。扩展时,不能扩展已经走过的节点(要判重)。

广搜最优解一般是求操作步骤最少,注意判重(可以用set来判重)。

三、双向广搜(DBFS):待更新。

四、A*算法在BFS算法中,若对每个状态n都设定估价函数f(n)=g(n)+h(n),并且每次从Open表中选节点进行扩展时,都选取f值最小的节点,则该搜索算法为启发式搜索算法,又称A算法。

g(n) : 从起始状态到当前状态n的代价
h(n) : 从当前状态n到目标状态的估计代价
广搜可以看作:f(n)=g(n)(无h(n)这项),A*的关键是如何设计估计函数h(n),如何对估计函数做限制,确保能找到最优解。

由于是有根据地去估计,因此不可能估计出比真实值还小的数,即真实代价≥估计代价。

估计函数实际上是一种乐观的估计,在这种乐观估计的前提下,越悲观越靠近真实值。即估计值在满足≤真实值的前提下,估计函数的值越大越好。

五、迭代加深搜索算法:总体上按照深度优先算法方法进行。多次从起点出发做深搜,每次规定一个深度限制dm。劣势:会有重复搜索,从时间效率上不如广搜,好处是因为有步数的限制所以不用判重。

广搜有可能比深搜号,但广搜扩展出来的情况可能更多。

六、Alpha-Beta剪枝

极大极小搜索法(待更新)

 

posted @ 2018-07-27 01:46  敲代码不BB  阅读(243)  评论(0编辑  收藏  举报