第一章 搜索算法 第二节 广度优先搜索

http://www.jiong3.cn/blog/article.asp?id=198

 

2、广度优先搜索
   在说明这个算法之前,先来看看一道题:
   例2. 可恶机关
      “城管大队”在一次尾行跟踪邪恶的白雪公主队伍时遇到了一个机关。这个机关长R宽C,被分为R*C个小方格。其中,一些方格上有箱子,一些方格上有按钮。如果要解决这个机关,就必须把所有箱子推到这些按钮上面。可恶的是,邪恶的白雪公主为了不让城管大队太快解决,就设置了一些很恶心的障碍物。而且,箱子上被施了魔法,只能推不能搬不能拉。当所有按钮被按下时,机关就被解决。请您帮助城管大队以最小的步数解决这个可恶的机关,赶紧追上邪恶的白雪公主队伍吧!
当然,箱子和人都只能以格子为单位移动,不存在一部分在格内一部分在格外的情况;只能向四个方向推,箱子和推箱子的队员都不能穿墙。推动的定义是,前进方向被箱子挡住,且箱子在顺着前进方向的下一格不是箱子或者障碍物,那么就可以推着箱子和箱子一起前进一步。
      这道题假如使用我们上面介绍的深度优先搜索算法,显然不可能出解,因为很容易会出现“绕圈子”的情况,也即这道题的情况所列出来的树的深度不固定,这种情况是不能使用深度优先搜索的。那么,我们如何解决这道题呢?这时,我们介绍的算法——广度优先搜索,就大大发挥了用处。
      广度优先搜索顾名思义,列出来的树中,我们不“一条路走到黑”了,我们很贪心地先把每个结点能走到的情况走一次,看看有没有目标状态,如果没有的话重复这个操作。同时,由于深度是一层一层搜的,所以搜得的解一定是最优解。
      那么回归这题,我们如何解决呢?方法很简单:对于当前人所在位置,把所有能行动的可能性都保存起来,等待该层结点搜索完毕后继续搜索下一层。具体实现时,我们需要注意两个问题,一是重复结点需要判重(以防止“绕圈子”现象),二是采用队列来记录情况(具体实现在数据结构篇会详细介绍)。
     [附录]1、广度优先搜索的伪代码
      Procedure BreadthFirstSearch(InitialStat:Statetype);
      begin
        Enqueue(InititalState);
        While Not EmptyQueue do
           begin
             DeQueue(State);
             For Operand:=1 to OperandCount(State) do
               begin
                 NewState:=DoOperand(State,Operand);
                 If Answer(NewState) then PrintAns;
                 Else Enqueue(NewState);
               end;
           end;
      end;
posted @ 2008-12-22 11:15  jesonpeng  阅读(247)  评论(0编辑  收藏  举报