首页 > 其他 > 详细

队列&广搜

时间:2019-04-12 21:28:25      阅读:195      评论:0      收藏:0      [点我收藏+]

搜索里有深搜,又有广搜,而广搜的基础就是队列。

队列是一种特殊的线性表,只能在一段插入,另一端输出。输出的那一端叫做队头,输入的那一端叫队尾。是一种先进先出(FIFO)的数据结构。

正经的队列:

头文件:#include <queue>

入队:q.push(要入队的数)

返回第一个元素:q.front( )

从队列中移除第一个元素:q.pop( )

查看队列中元素的个数:q.size( )

返回队列的最后一个元素:q.back( )

用数组模拟的队列:

可以定义数组q[100001](可大可小)

队头为head,队尾为tail

注意:

技术分享图片

 

如图,head指向第一个实际元素的前一个位置,tail指向最后一个实际元素的位置

无论数组多大,总会有个界限,入队过多会溢出,而前面出队时会有空出来的位置,所以我们可以把一个数组循环使用。

代码如下:

void rudui(int x)
{tail++:
   if(tail==n+1)
     tail=1;
  if(tail==head)//入队要判满
   {printf("操作无效,队列已满");
    return;}
    q[tail]=x;
}

说了些基本定义,再来说说应用。

队列的应用和广搜是分不开的。

那什么是广搜?

就是一层一层的搜索,从第0层开始,每层都枚举出可能的情况,直到找到符合要求的情况为止

如图:

技术分享图片

 

放个模板

这里是用数组模拟队列
int  bfs()
{ 队列初始化;
   head=0;tail=1;//记住tail指向最后一个实际元素!!
  do{
         head++;//head指向带扩展节点
       for(int i=1;i<=max;i++)//节点如何扩展
         {
                   if(子节点符合条件)
                       {tail++;该节点入队;
                          if(与原来有重复)
                               { 删除该节点;tail--;  
                               }
                           else
                                {if(找到目标)输出并退出;
                                 }
                         }
          }    
      }while(head<tail);//队列不空就继续搜索
}

 

 举个栗子:

洛谷P1451求细胞数量

技术分享图片

这个题就是广搜的典型例题。

在这道题中,所有非0数都可以看做是1,因为它们的值不影响判断。这样就可以用一个bool数组a[1001][1001]来表示这个矩阵

通过样例可以知道,矩阵的输入是没有空格的,所以要用字符型输入(这是个坑)

既然我们决定用bool型数组(只有0,1),而且还有前面那个坑。为了防止毒瘤的非法读入,我们先将整个a数组置为1。我们输入时判断一下,如果输入的字符是0,就把对应位置置为0。

然后就是搜索了。

先在main里找到1,再进行搜索,会省时间。

搜索时,记录下当前的i,j。从i,j的上下左右搜索,如果是1,就将这个位置的坐标放入队中,并将这个位置置为0,防止重复

入队的同时将队头出队,一直到队空为止,完成一次搜索,计数器加1.

代码如下:

#include<iostream>
#include<cstdio>
using namespace std;
int n,m,num,dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};//预处理出4个方向
bool a[101][101];
void justdoit(int p,int q)
{   a[p][q]=0;
    int x,y,head,tail,i;
    int h[10001][3];
    num++;
    h[1][1]=p;h[1][2]=q;//h[head][1]为横坐标,h[head][2]为纵坐标
    head=0;tail=1;
    do{
        head++;
        for(int i=0;i<=3;i++)
        {x=h[head][1]+dx[i];y=h[head][2]+dy[i];
           if((a[x][y])&&(x>=0)&&(y>=0)&&(x<m)&&(y<n))
           {tail++;
             h[tail][1]=x;//坐标入队
             h[tail][2]=y;
             a[x][y]=0;
           }
        }
    }while(head<tail);
}//其实就是套模板
int main()
{char c[101];
 scanf("%d %d",&m,&n);
 for(int i=0;i<=m-1;i++)
  {for(int j=0;j<=n-1;j++)
    a[i][j]=1;
  }
  for(int i=0;i<m;i++)
  { 
    scanf("%s",c);
    for(int j=0;j<n;j++)
     {if(c[j]==0){a[i][j]=0;
     }
     }
  }
  for(int i=0;i<m;i++)
  {for(int j=0;j<n;j++)
    if(a[i][j])justdoit(i,j);
  }
  printf("%d",num);
}

 

队列&广搜

原文:https://www.cnblogs.com/lcez56jsy/p/10698598.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!