回忆BFS

回忆BFS

上次我们已经回忆了简单的dfs,相信大家对搜索已经有了一点了解,对搜索也不会那么陌生了。那么我们现在就来更加深入的了解一下搜索,学习更上一层难度的搜索方法————————————BFS!!

 

哇!一听BFS这个方法的名称,就让人觉得是那么的神圣!那么难!(咳咳,难其实也没那么难~~),那么,接下来就让我们进入神奇的BFS之旅吧!

 

抽象“概念”:BFS顾名思义,更在乎搜索的范围,每次都尽可能把能搜索到的范围都搜索到,然后逐步扩展。这样在求最短步数,或者最短的序列问题时,第一次搜到的肯定时一般的最优解。

 

接下来给大家一道框架题目:

  有n个城市,给定城市a到城市b的路径(当然不止连同两个城市),求从城市S带城市B的最短路。

  题目分析:诶诶?这不是图论中的最短路吗??怎么会是BFS??嘿嘿~当然是楼。具体看模板:

   int adj[N][N],S,T,n;

   int q[N]={},s[N]={},head=0,tail=0;

   ……(此处应为输入及初始化)

   q[++tail]=S;vis[S]=true;(将初始化节点S塞入队列)

   while (head<=tail){

     int X=a[head++];//取对头

     for (inti=1;i<=n;i++)

       if (adj[x][i]&&!vis[i]){

         q[++tail]=i;vis[i]=true;

         if (i==T)break;处理;//ok

}

}

好吧这个模板其实是有点抽象的。。

 

二、接下来是求最短路径的代码(其实也就改了一点):

   int adj[N][N],S,T,n;

   int q[N]={},s[N]={},head=0,tail=0,dis[N]={};

   ……(此处应为输入及初始化)

   q[++tail]=S;vis[S]=true;(将初始化节点S塞入队列)

   while (head<=tail){

     int X=a[head++];//取对头

     for (inti=1;i<=n;i++)

       if (adj[x][i]&&!vis[i]){

         q[++tail]=i;vis[i]=true;//将新状态加入队尾

         dis[i]=dis[x]+1;//步数+1

         if (i==T)break;处理;//ok

}

}

 

啊哈!这就是一道不太正宗的模板!接下来一道真正的模板:

int bfs(){

  初始化,初始状态存入队列;

  队列首指针head=0;尾指针 tail=1;

  do{

    指针head后移以一位,指向带扩展节点;

    for (inti=1;i<=max;i++){

      if (子节点符合条件){

         tali指针加一,把新节点存入队尾;

         if (新节点已产生节点重复) 删去该节点(取消入队,tail减一);

           else

             if(新节点是目标节点) 输出并退出

      }

    }

  }while(head<tail);//队列为空

}

 

三、经典例题:

 

一、勇士与公主

  题目简述:有一个n*n的矩阵,其中矩阵中的元素分别有'.'(空地),'#'(墙),'T'(勇士的位置)和'S'(公主的位置)。其实每次都能上下左右走,问最少走几步?

 

  题目分析:额~~这道题其实是我简化过10000倍的~~应该很简单吧~~开始时就只要把墙处理一下,在找出骑士位置然后公主位置后按题一bfs就行了。

 

  那么具体代码如下(完整代码就只发这么一题):

 

 #Include<bits/stdc++.h>

 using namespacestd;

 intxx,yy,xx1,yy1,n,q[1001][3]={},head=0,tail=0,dis[1001][1001]={};

 char ch;//输入用

 bool f[1001][1001]={};//判断当前路是否可走

int dx[5]={0,0,1,-1}

int dy[5]={1,-1,0,0}//方向

 void bfs(){

    for (inthead=1;head<=tail;head++){

      for (inti=0;i<=3;i++){

        inttx=q[head][1]+dx[i],ty=q[head][2]+dy[i];

        if (f[tx][ty){

      if (tx==xx1&&ty==yy1)cout<<dis[tx][ty];

        else {

          q[+tail][1]=tx;q[tail][2]=ty;

}

      }

     }

}

 int main(){

   cin>>n;

    for (inti=1;i<=n;i++)

      for (intj=1;j<=n;j++){

        f[i][j]=1;//现将范围内的东东赋值为可走,避免走出接

        if (ch=='T')xx=i,yy=j;//记录骑士位置

        if (ch=='S') xx1=i,yy1=j;//记录公主位置

         if (ch=='#')f[i][j]=0;//墙,不能走

      }

    q[+tail][1]=xx;q[tail][2]=yy;

    bfs();//bfs

    return ;

}

 

{因为代码是现成敲的,所以不保证对,但致思路是没问题的

 

二、思考:如果加上守卫,没杀死一个守卫需要耗费一个单位时间,那怎么办呢?

 

  题目分析:还是一样,如果当前点有守卫,那么就记录状态,一旦遇到,就额外多加一个单位的时间,再讲状态清空,继续bfs。

 

  这题代码就不给了,大家自己想把。

猜你喜欢

转载自blog.csdn.net/huang_ke_hai/article/details/79275253
BFS