第十周 广度优先搜索(BFS)
1.抓住那头牛 百练4001
2.迷宫问题 百练4127
3.鸣人和佐助 百练6044
4.八数码问题(Eight) 百练 1077为单组数据 HDU 1043 为多组数据
百科提供的知识点:
广度优先搜索是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。
深度优先搜索用栈(stack)来实现,整个过程可以想象成一个倒立的树形:
1、把根节点压入栈中。
2、每次从栈中弹出一个元素,搜索所有在它下一级的元素,把这些元素压入栈中。并把这个元素记为它下一级元素的前驱。
3、找到所要找的元素时结束程序。
4、如果遍历整个树还没有找到,结束程序。
广度优先搜索使用队列(queue)来实现,整个过程也可以看做一个倒立的树形:
1、把根节点放到队列的末尾。
2、每次从队列的头部取出一个元素,查看这个元素所有的下一级元素,把它们放到队列的末尾。并把这个元素记为它下一级元素的前驱。
3、找到所要找的元素时结束程序。
4、如果遍历整个树还没有找到,结束程序。
关键问题:
判重à新扩展出的节点如果和以前扩展出的节点相同,则这个新节点就不必再考虑
八数码问题有解性的判定(奇偶剪枝)
八数码问题的一个状态实际上是0~8的一个排列。对于任意给定的初始状态和目标,不一定有解,即从初始状态不一定能到达目标状态。因为排列有奇排列和偶排列两类,从奇排列不能转化成偶排列或相反。
如果一个数字0~8的随机排列,用F(X) (X!=0)表示数字X前面比它小的数(不包括'0')的个数,全部数字的F(X)之和为Y=∑(F(X)),如果Y为奇数则称该排列是奇排列,如果Y为偶数则称该排列是偶排列。
871526340排列的 Y=0+0+0+1+1+3+2+3=10,所以是偶排列。
871625340排列的Y=0+0+0+1+1+2+2+3=9,所以是奇排列。
因此,可以在运行程序前检查初始状态和目标状态的奇偶性是否相同,相同则问题可解,应当能搜索到路径。否则无解。
广度优先搜索的代码框架
BFS()
{
初始化队列;
while(队列不为空且未找到目标节点)
{
取队首节点扩展,并将扩展出的非重复节点放入队尾;
必要时要记住每个节点的父节点;
}
}
简单BFS模板:
q.push(head); //起始节点加入队列:
sign[head] = true; //标记起始节点
while(!q.empty()) //当队列不为空时
{
int temp = q.front();
q.pop();
… //访问temp,并标记temp已被访问过(sign[temp])
… //将temp的子相关节点加入队列(check())
q.push(temp相关节点);
}