搜索 BFS

来源:互联网 发布:如何优化企业发展环境 编辑:程序博客网 时间:2024/06/09 14:10

  广搜:就是先往“广”的地方找,再一层一层的推下去,换句话手就是先把同层的找完再往下层去找,是一种扩散的思想。每个深度为t的节点一定会在深度为t+1的节点前找到。主要用队列来实现(如果你不明白什么是队列,不用着急,因为依旧可以实现广搜)。下面介绍一下几道基础的广搜题。

勘探油田结构体实现

Description

  某石油勘探公司正在按计划勘探地下油田资源。他们工作在一片长方形的地域中,首先将该地域划分为许多小正方形区域,然后使用探测设备分别探测每一块小正方形区域是否有油。若在一块小正方形区域中探测到有油,则标记为@’,否则标记为’*’。如果两个相邻区域都为@,那么它们同属于一个石油带,一个石油带可能包含很多小正方形区域,而你的任务是要确定在一片长方形地域中有多少个石油带。所谓相邻,是指两个小正方形区域上下、左右、左上右下或左下右上同为@’。

Input

  输入数据将包含一些长方形地域数据,每个地域数据的第一行有两个正整数mn,表示该地域为m*n个小正方形所组成,如果m0,表示所有输入到此结束。否则,后面m1m100)行数据,每行有n1n100)个字符,每个字符为’@’或’*’,表示有油或无油。每个长方形地域中,’@’的个数不会超过100

Output

每个长方形地域,输出油带的个数,每个油带值占独立的一行。油带值不会超过100

 

用广搜的思想解释一下bfs部分,首先广搜需要一个起始点因此调用函数是你需要给出这个起始点。其次,广搜是逐层寻找所有和起始点有联系的部分也就是这题里的八个方向进行寻找为里面的for (j = 0; j < 8; j++)。最后你每找到一个还需要寻找它八个方向,因此要修改起始点坐标Q[top].x = tx;Q[top++].y = ty;再将top++,使得for (i = 0; i < top; i++)多进行一次。

代码如下:


#include<stdio.h>int m, n;char grid[105][105];/*控制上下左右移动的数组(-1,-1)(-1,0)(-1,1)(0,1)(1,1)...*/ int x[8] = {-1,-1,-1,0,0,1,1,1};int y[8] = {-1,0,1,-1,1,-1,0,1};struct node{int x, y;}Q[10005];void bfs(int a, int b){int top = 0, i, j, tx, ty;Q[top].x = a;Q[top++].y = b;grid[a][b] = '*';//每记录一个油井则把@变成* for (i = 0; i < top; i++)//有几个油井点进行几个八个方向的判断 {for (j = 0; j < 8; j++){tx = Q[i].x + x[j];//上下左右进行移动 ty = Q[i].y + y[j];if (tx >= 0 && ty >= 0 && tx < m && ty < n && grid[tx][ty] == '@'){grid[tx][ty] = '*';//油井点增加 Q[top].x = tx;Q[top++].y = ty;}}}}int main() {int i, j, cnt;//cnf油井数 while (scanf("%d%d", &m, &n), m)//m行n列 {for (i = cnt = 0; i < m; i++){scanf("%s", grid[i]); }for (i = 0; i < m; i++){for (j = 0; j < n; j++){if (grid[i][j] == '@'){cnt++;bfs(i, j);//每找到一个油井就以这个点为起点进行一次广搜目的把同一油田里油井全找到 }}}printf("%d\n", cnt);}return 0;}

迷宫(stl队列实现)

  定义一个二维数组它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。

Input

一个n×mn<=20,m<=20的二维数组,表示一个迷宫。数据保证有唯一解。

Output

左上角到右下角的最短路径,格式如样例所示。

Sample Input


0 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 1 1 0 0 0 0 1 0

Sample Output


(0, 0) (1, 0) (2, 0) (2, 1) (2, 2) (2, 3) (2, 4) (3, 4) (4, 4)

先介绍一下队列的六个函数front()返回队列头部数据back()返回队列尾部数据push()将数据从尾部输入pop()将数据从头部拿出empty()判断队列是否为空size()返回队列中数据个数

代码如下:

#include<cstring>#include <iostream>#include <queue>//头文件 #include <limits.h>#include <algorithm>#define A 21 using namespace std;const int BLOCK=1;int Maze[A][A];pair<int,int>path[A][A];//定义队列用path二维数组存储 int dx[]={1,-1,0,0};//确定四个方向(1,0)(-1,0)。。。 int dy[]={0,0,1,-1};void bfs(int ex,int ey){    queue <pair<int,int> > q;//定义q     q.push(make_pair(ex,ey));         path[ex][ey]=make_pair(-1,-1);//记录终点结束条件值     Maze[ex][ey]=BLOCK;           //标志为不可走    while(!q.empty())//如果队列里面非空     {        pair<int,int>fa =q.front();//将头部数据赋给fa         q.pop();//处理过的出队列         for(int i=0;i<4;i++)//四个方向         {            int nx=dx[i]+fa.first;int ny=dy[i]+fa.second;            if(nx>=0&&ny>=0&&nx<A&&ny<A&&!Maze[nx][ny])             {                path[nx][ny]=fa;     //记录路径(经过该点的路线的上一个点)                if(0==nx&&0==ny)     //找到起点可以返回                return ;                q.push(make_pair(nx,ny));//入队列等待下一次搜索                 Maze[nx][ny]=BLOCK;  //入队列的方格,可以马上置为不可走状态}        }    }}int main(){int n,m;scanf("%d%d",&n,&m);    for(int i=0; i<n; i++)        for(int j=0; j<m; j++)        scanf("%d",&Maze[i][j]);        bfs(n-1,m-1);//需要确定一个起始点进行广搜         int x=0,y=0;            ///起点开始输出路径点        while(x!=-1)        {            printf("(%d, %d)\n",x,y);            int nx=path[x][y].first;            int ny=path[x][y].second;            x=nx,y=ny;                      }    return 0;}

可以看出和上一题代码几乎相同,仅仅只是用队列确定了一下搜索的先后顺序也已。

最后再说一下广搜,广搜就是先确定搜索顺序按照既定规则由起始点开始进行铺盖式搜索,没多出一个点就要多进行一次。






1 0
原创粉丝点击