A*算法与8数字谜题(参见《算法》P226习题2.5.32)

    A*算法的目的是找到一条从起始状态到最终状态的最短路径。算法

    在A*算法中,须要在每一个点计算启发函数:f(S) = g(S) + h(S),其中g(S)是从起点到S点的距离,h(S)是对从S点到终点的最短距离的估计值。数据结构

    若是把g(S)看成深度,又令h(S) = 0,则A*算法就变成了BFS函数

    A*算法对BFS的改进在于把BFS所用到的队列改为按启发函数值排列的优先队列。spa

    假设从状态S抵达终点的最短距离为H(S),那么启发函数中的h(S)必须知足h(S)<= H(S)。在此基础上,h和实际的距离越接近,须要计算的节点就越少,效果就越好。若是h(S) = 0,此时A*算法就变成了BFS,效果最差。设计

 

    在解8数字谜题时,若是按照BFS的思路,咱们每次扩展四个节点,分别是空格上移、下移、左移和右移(固然,大多数节点是没法彻底扩展这四个方向的),一层层搜索以后,若发现了目标状态,则从目标状态节点开始向父节点回溯,由此就能够获得一个步数最少的解法了。可是BFS是盲目的,所以在搜索过程当中它搜索了不少意义不大的节点。因而咱们开始设计一个加入了必定启发信息的A*算法(其思路相似于分支限界),代码以下(参见P223 2.5.4.6小节)blog

 

A*()
{
	// open表,用优先队列实现,用来保存待扩展的节点(改进自BFS中的队列)。
	PriorityQueue open;
    
	// closed表,用HASH表或者其余可以高效检索的数据结构实现,用来保存已经扩展过的节点(能够考察一个状态是否已经被产生过)。
	SymbolTable closed;

	open.Add(起始节点);
     
    while(!PriorityQueueEmpty(open))
    {
		// 从open表中弹出一个最优的待扩展节点
        S = PriorityQueueDeleteMax(open)); 

        closed.Insert(S);
         
        // 若是S就是目标状态则结束
        if(S == GOAL)
        {
            return OVER;
        }
         
        // 尝试扩展S的全部子节点
        while(childS = S.nextChild())
        {
            // 若是当前节点还没有被产生过
            if(!closed.isInclude(childS))
            {
                // 则将这个节点添加到open表中
                PriorityQueueInsert(open,childS);
            }
        }
    }
}
相关文章
相关标签/搜索