BFS 典型的迷宫问题

这个是BFS搜索的典型问题,好好整理一下:

给定一个迷宫,入口为左上角,出口为右下角,问是否有路径从入口到出口,若有则输出一条这样的路径。注意移动可以从上、下、左、右、上左、上右、下左、下右八个方向进行。迷宫输入0表示可走,输入1表示墙。易得可以用1将迷宫围起来避免边界问题。本题采用BFS算法给出解。注意,利用BFS算法给出的路径必然是一条最短路径。

input:

1

6 8

0 1 1 1 0 1 1 1

1 0 1 0 1 0 1 0

0 1 0 0 1 1 1 1

0 1 1 1 0 0 1 1

1 0 0 1 1 0 0 0

0 1 1 0 0 1 1 0

output:

YES

(1,1) (2,2) (3,3) (3,4) (4,5) (4,6) (5,7) (6,8)

基本思路:

采用BFS的思路,每个位置相当于一个结点,用BFS进行广度搜索,相当于往外一环一环扩散的感觉,最后看能否达到出口的位置。

实现以及技巧:

1.基本的数据结构:相比对于一棵树的BFS来说,这里的BFS中的Node是一个坐标,因此要自定义好结点,typedef struct Node{int x; int y;}Node;BFS里面要用到队列,对基本的队列的库函数的声明和使用要熟悉,Q.size() Q.push(Node) Q.front() 以及Q.pop()

2.关于path的问题:由于要存储路径信息,这里的path是一个二维的指针数组,注意这种声明以及初始化的方式:声明Node **path;初始化:

path=new Node*[MAXL];

for(i=0;i<=MAXL;i++)

{path[i]=new Node[MAXH];}

应该还有其他的表述方式,总之要会用一个,这里涉及到二维时候的指针还是挺麻烦的。

3.还要注意每次path的更新点的选择问题,在每次元素入队的时候,比如当前元素为now,检查它周围的8个点,让没有墙的点入队,比如一个没有墙的点是temp就在这个位置上更新,path[temp.x][temp.y]=now。

4.path输出的问题也很重要,这个最好就记下来,就是递归输出,比较典型,具体看代码的outputpath函数。

5.考虑向周围移动的时候:向周围的8个点移动的时候可以先设置好一个二维数组:

Node move[8]={{1,0},{-1,0},{0,1},{0,-1},{1,1},{-1,1},{-1,-1},{-1,1}};

之后一个循环,把对应的x y值加上去就好,这样比较省事。注意结构体赋初值的时候也可以用这种小括号的形式:Node start={1,1};

6.还有一点容易忽略,想周围移动的时候,已经探测过的点要做个标记,比如标记成-1或者类似的,这样就不会绕回去了,否则有可能形成一个环。

7.还有其他的技巧,就是在地图初始化的时候,在周围加上一圈的围墙,这样在具体BFS的时候就不用再考虑边界的问题了。

具体代码如下:

//http://blog.csdn.net/that163/article/details/8069764
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define MAXH 20
#define MAXL 20
using namespace std;

typedef struct Node{
    int x;
    int y;
}Node;

//记录地图信息
int maze[MAXH][MAXL];
//记录路径信息
//Node*path[MAXH][MAXL];
Node **path;
Node move[8]={{1,0},{-1,0},{0,1},{0,-1},{1,1},{-1,1},{-1,-1},{-1,1}};

bool BFS(Node start,Node end)
{
    int i;
    Node tempN;
    Node tempNM;
    queue<Node>Q;
    Q.push(start);
    maze[start.x][start.y]=-1;

    //while(tempN.x!=end.x&&tempN.y!=end.y&&Q.size!=0)
    while(Q.size()!=0)
    {
        tempN=Q.front();
        Q.pop();
        //遍历8个方向全部的点
        for(i=0;i<8;i++)
        {
            tempNM.x=tempN.x+move[i].x;
            tempNM.y=tempN.y+move[i].y;
            //若是移动之后的点 位置是0 表示可以通过
            if(tempNM.x>=1&&tempNM.y>=1&&tempNM.x<=end.x&&tempNM.y<=end.y&&maze[tempNM.x][tempNM.y]==0)
            {
                //孩子结点入队
                Q.push(tempNM);
                //已经尝试过的点标记成-1
                maze[tempNM.x][tempNM.y]=-1;
                path[tempNM.x][tempNM.y]=tempN;
            }
        }

    }

    if(tempN.x==end.x&&tempN.y==end.y)
    {return true;}
    else
    {return false;}

}

void outputpath(Node end)
{
    //可以递归输出
    Node temp=end;
    if(end.x==1&&end.y==1)
    {
        printf("(%d,%d)",end.x,end.y);
        return;
    }
    else
    {
        //取出指针的内容
        temp=path[temp.x][temp.y];
        outputpath(temp);
        if(temp.x!=1&&temp.y!=1)
        {printf("(%d,%d)",temp.x,temp.y);}
    }

    return;

}

int main()
{
    freopen("in.txt","r",stdin);
    int hang,lie,N;
    int i,j;
    scanf("%d",&N);
    while(N--)
    {
        //输入部分
        scanf("%d%d",&hang,&lie);
        for(i=1;i<=hang;i++)
        {
            for(j=1;j<=lie;j++)
            {
                if(j==lie)
                {
                    scanf(" %d",&maze[i][j]);
                }
                else
                {
                    scanf("%d",&maze[i][j]);
                }
            }
        }

        Node start={1,1};
        //注意结构体的这种用中括号来赋值的方式
        Node end={hang,lie};

        //二维指针数组的规定初始值的方式
        //此时path是一个指向一维指针数组的指针
        path=new Node*[MAXL];
        for(i=0;i<=MAXL;i++)
        {path[i]=new Node[MAXH];}

        //调用BFS函数进行搜索 更新path矩阵信息
        bool connect=BFS(start,end);
        if(connect)
            puts("YES");
        else
            puts("NO");

        //输出路径信息
        outputpath(end);

        printf("(%d,%d)\n",6,8);

    }

    return 0;
}
时间: 2024-11-02 20:43:55

BFS 典型的迷宫问题的相关文章

ACM:图的BFS,走迷宫

题目: 一个网格迷宫由n行m列的单元格组成,每个单元格要么是空地(用1表示),要么是障碍物(用0来表示).你的任务是找一条从起点到终点的最短移动序列,其中UDLR分别表示往上.下.左.右移动到相邻单元格.任何时候都不能在障碍格中,也不能走到迷宫之外.起点和终点保证是空地. 分析:图的BFS. #include <iostream> #include <string> #include <queue> using namespace std; const int MAXN

[bfs] Jzoj P3522 迷宫花园

Description 给定一个一定存在从起点到终点的路径的四联通迷宫.已知Tar左右方向移动的时间为1,上下移动的时间为未知实数v.求当Tar从起点到终点的最短移动时间为已知实数L时,未知实数v是多少. Input 输入数据包含多个测试点.第一行为一个整数T,表示测试点的数目. 对于每一个测试点,第一行包含实数L和两个整数R,C.R为迷宫的上下长度,C为迷宫的左右长度. 之后的R行,每行包含C个字符.其中空格表示空地,S表示起点,E表示终点,#表示围墙. Output 对于每一个测试点,在单独

(图 BFS)走迷宫

题目: 给一个迷宫,求出从起点到终点的路径.迷宫 src.txt 文件内容如下,第一行是迷宫的行列数,后面行是迷宫,1表示可行走,0表示不可以通过,起点是最左上角,终点是最右下角: 1 6 5 2 1 1 0 1 1 3 1 0 1 1 1 4 1 0 1 0 0 5 1 0 1 1 1 6 1 1 1 0 1 7 1 1 1 1 1 解析: 其实就是图的广度优先遍历. 代码及运行结果: 1 #include <iostream> 2 #include <queue> 3 #inc

简单BFS +打印路径 迷宫问题 POJ - 3984

#include<cstdio> #include<iostream> #include<cstring> #include<string> #include<stack> #include<queue> using namespace std; int nex[4][2]= { {0,1},{1,0},{0,-1},{-1,0} }; typedef struct { int x,y; } Point; int a[10][10],

POJ 2049-Finding Nemo(三维bfs解决类迷宫问题)

Finding Nemo Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 7902   Accepted: 1827 Description Nemo is a naughty boy. One day he went into the deep sea all by himself. Unfortunately, he became lost and couldn't find his way home. Therefo

bfs简单应用----迷宫问题

[week2-A] 东东有一张地图,想通过地图找到妹纸.地图显示,0表示可以走,1表示不可以走,左上角是入口,右下角是妹纸,这两个位置保证为0.既然已经知道了地图,那么东 东找到妹纸就不难了,请你编一个程序,写出东东找到妹纸的最短路线. Input 输入是一个5 × 5的二维数组,仅由0.1两数字组成,表示法阵地图. Output 输出若干行,表示从左上角到右下角的最短路径依次经过的坐标,格式如样例所示.数据保证有唯一解. Sample Input 0 1 0 0 00 1 0 1 00 1 0

POJ 3984 迷宫问题 bfs 难度:0

http://poj.org/problem?id=3984 典型的迷宫问题,记录最快到达某个点的是哪个点即可 #include <cstdio> #include <cstring> #include <queue> using namespace std; const int maxn=10; const int inf=0x3fffffff; struct pnt { int x,y; pnt(){x=y=0;} pnt(int tx,int ty){x=tx,y

迷宫问题(maze problem)——深度优先(DFS)与广度优先搜索(BFS)求解

1.问题简介 给定一个迷宫,指明起点和终点,找出从起点出发到终点的有效可行路径,就是迷宫问题(maze problem). 迷宫可以以二维数组来存储表示.0表示通路,1表示障碍.注意这里规定移动可以从上.下.左.右四方方向移动.坐标以行和列表示,均从0开始,给定起点(0,0)和终点(4,4),迷宫表示如下: int maze[5][5]={ {0,0,0,0,0}, {0,1,0,1,0}, {0,1,1,0,0}, {0,1,1,0,1}, {0,0,0,0,0} }; 那么下面的迷宫就有两条

广搜:codevs-3344(初步bfs)

一道典型的迷宫问题 小刚在迷宫内,他需要从A点出发,按顺序经过B,C,D--,到达最后一个点,再回到A点.迷宫内有些障碍,问至少走几步. 输入描述 Input Description 第一行有三个数n,m表示迷宫有n行,m列. 第2行到第n+1行,每行m个字符,可能是'A'..'Z','2','0' 其中,2表示障碍,0表示可以走.'A'..'Z'也可以走. 输出描述 Output Description 至少走几步可以按规定走完,如果不行,输出"Impossible" 读完题后发现这