广度优先搜索和深度优先搜索(迷宫)


广度优先搜索和深度优先搜索


诶,思来想去,还是要关于这个写一篇博客的。(毕竟当初为了看懂这两个东西并且自己写出代码,花了好长好长的时间。)上次蓝桥杯中出现了一道关于迷宫的题目,当时写了好久写不出来,很气,于是下定决心要把这两个东西看看懂。而最近又回到了图论的问题,于是这两玩意又出来了。。

第一次接触DFS,是在《啊哈,C》中 解救小哈 一问题的解决。

先来讲一下这两者的算法思想吧。(这里感谢我大oy)
广度优先搜索(BFS),也称为宽度优先搜索。其思想在图上画出来就像一个石子被丢进池塘中,激起的波纹。在图中,他从起点开始,记录下能够走到的位置,然后走到下一个点,同时把上一个点给标记掉(即不要往回走),然后下一个点,继续上面的操作。直到第一次出现重点,就可以结束了(若是找最短路径)。
深度优先搜索(DFS),俗称“不撞南墙不回头”,就从一条路开始,下一个点,下一个点,直至走到不能走到的点,然后回溯同时标记死胡同,走到能有下一条路的路口,向下一个没有标记的点走。

从算法思想来看,广度优先搜索适合找最短路径(要是题目要求输出最短路径长度,那就最简单了),而加上对上一点的记录,也就可以还原原来的路径。深度优先搜索个人认为更加适合有优先方向的题目,同时也可以还原路径。

而后,又在oj上写到这么一道题:

  • 题目描述

迷宫是一个二维矩阵,其中1为墙,0为路,3为入口,4为出口.要求从入口开始,从出口结束,按照 下,左,上,右 的顺序来搜索路径.

  • 输入

迷宫宽度w 迷宫高度h
迷宫第一行
迷宫第二行

迷宫第h 行

  • 输出

入口横坐标1 入口纵坐标1
横坐标2 纵坐标2
横坐标3 纵坐标3
横坐标4 纵坐标4

横坐标n-1 纵坐标n-1
出口横坐标n 出口纵坐标n

  • 样例输入

8 10
1 1 1 1 1 1 1 1
1 0 1 1 0 1 0 1
1 0 1 0 0 1 0 1
1 1 0 3 1 0 1 1
1 0 0 1 0 0 4 1
1 0 0 0 0 1 1 1
1 0 1 0 0 1 0 1
1 0 1 0 0 0 1 1
1 1 1 1 0 0 0 1
1 1 1 1 1 1 1 1

  • 样例输出

3 3
2 3
2 4
2 5
3 5
3 6
3 7
4 7
4 6
4 5
4 4
5 4
6 4


这是最直接明了的迷宫问题了,找出路径,并输出路径就行了,且这里使用优先队列思想。
这题当时使用c语言写的一段DFS的代码。(这里没有用上stl库的队列,还自己写了一个)

#include <cstdio>
#include <iostream>
#include <vector>
#include <cstring>
#include <stack>
#include <queue>
 
#define len 999
using namespace std;
 
typedef struct node
{
    int x;
    int y;
    int f;
} position;
 
int Next[4][2] = {{1,0},{0,-1},{-1,0},{0,1}};
int row,line,start_x,start_y,end_x,end_y,flag = 0,lon = 0;
int maze[len][len], book_maze[len][len];
position que[len][len];
position book_que[len*len];
void Search_the_position(int p,int &x,int &y);
void dfs(int x,int y);
void way_print();
 
int main()
{
    cin>>line>>row;
    for (int i=0; i<row; i++)
        for (int j=0; j<line; j++)
            scanf("%d", &maze[i][j]);
 
    Search_the_position(3,start_x,start_y);
    Search_the_position(4,end_x,end_y);
    maze[end_x][end_y] = 0;
    maze[start_x][start_y] = 0;
 
    book_maze[start_x][start_y] = 1;
    dfs( start_x, start_y);
    way_print();
 
    return 0;
 
}
void Search_the_position(int p,int &x,int &y)
{
    for (int i=0; i<row; i++)
        for (int j=0; j<line; j++)
            if (maze[i][j] == p)
            {
                x = i;
                y = j;
                return;
            }
}
 
void dfs(int x,int y)
{
    int now_x,now_y,step_possible;
 
    if (flag)
        return;
    if (x==end_x && y==end_y)
    {
        flag = 1;
        return;
    }
 
 
    for (step_possible=0; step_possible<4; step_possible++)
    {
        now_x = x + Next[step_possible][0];
        now_y = y + Next[step_possible][1];
 
        if (now_x<0||now_x>=row||now_y<0||now_y>=line)
            continue;
 
        if (book_maze[now_x][now_y]==0 && maze[now_x][now_y]==0)
        {
            book_maze[now_x][now_y] = 1;
            que[now_x][now_y].x = x;
            que[now_x][now_y].y = y;
            dfs(now_x,now_y);
        }
    }
}
void way_print()
{
    int mx = end_x,my = end_y;
    int nx,ny;
    int i = 0;
 
    nx = que[mx][my].x;
    ny = que[mx][my].y;
 
    while (mx!=start_x||my!=start_y)
    {
        book_que[i].x = mx;
        book_que[i].y = my;
 
        mx = nx;
        my = ny;
        nx = que[mx][my].x;
        ny = que[mx][my].y;
        i++;
    }
 
    cout<<start_y<<" "<<start_x<<endl;
 
    while(i--)
    {
        cout<<book_que[i].y<<" "<<book_que[i].x<<endl;
    }
}

代码不难。

之后又是另一道题:

  • 题目描述

设计一个算法找一条从迷宫入口到出口的最短路径。

  • 输入

迷宫的行和列m n

迷宫的布局

  • 输出

最短路径

  • 样例输入

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

  • 样例输出

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


这题 可以用来练习BFS,代码如下(这题是用c写的,而且不知道为什么当时都放在main函数里面去了,下次一定要注意- -。)

#include <stdio.h>
#include <stdlib.h>
 
typedef struct note
{
    int x;
    int y;
    int f;
    int s;
} seat;
 
int next[8][2] = {{0,1},{1,0},{0,-1},{-1,0},{1,1},{-1,1},{1,-1},{-1,-1}};
void Init_que(seat*, int, int,int );
void Print(int ,seat*);
int main()
{
    int w,h;
    scanf("%d%d", &h, &w);
 
    seat que[w*h+1];
 
    int labyrinth [w][h] ;
    int book_labyrinth [w][h] ;
    int head,tail;
    int i,j,k,startx,starty,tx,ty,flag;
    int endx,endy;
 
    for (j=0; j<h; j++)
    {
        for (i=0; i<w; i++)
        {
            scanf("%d", &labyrinth[i][j]);
        }
    }
 
    startx = 0;
    starty = 0;
    endx = w-1;
    endy = h-1;
 
    for (j=0; j<h; j++)
        for (i=0; i<w; i++)
            book_labyrinth[i][j] = 0;
 
    head = 1;
    tail = 1;
 
    Init_que(que,tail,startx,starty);
    tail++;
    book_labyrinth[startx][starty] = 1;
 
    flag = 0;
 
    while (head<tail)
    {
        for (k=0; k<=7; k++)
        {
            tx = que[head].x+next[k][0];
            ty = que[head].y+next[k][1];
 
            if (tx<0||tx>w-1||ty<0||ty>h-1)
                continue;
 
            if (labyrinth[tx][ty]==0 && book_labyrinth[tx][ty]==0)
            {
                book_labyrinth[tx][ty] = 1;
 
                que[tail].x = tx;
                que[tail].y = ty;
                que[tail].f = head;
 
                que[tail].s = que[head].s + 1;
                tail++;
            }
 
            if (tx==endx && ty==endy)
            {
                flag = 1;
                break;
            }
        }
 
        if (flag == 1)
            break;
 
        head++;
    }
    Print(tail, que);
 
    return 0;
}
 
void Init_que(seat *que, int tail, int startx, int starty)
{
    que[tail].x = startx;
    que[tail].y = starty;
    que[tail].f = 0;
    que[tail].s = 0;
}
 
 
 
void Print(int tail, seat *que)
{
    int goback = que[tail-1].f;
 
    printf("(%d,%d)\n", que[tail-1].y+1, que[tail-1].x+1);
    while(goback!=0)
    {
        printf("(%d,%d)\n", que[goback].y+1, que[goback].x+1);
        goback = que[goback].f;
    }
 

代码也不难,用队列实现而不是用递归(在班主任敲击下,改)。

而这里的所有代码还只是针对迷宫,还没有体现其他的图的遍历,而那之后的算法与代码,将会在之后的博客中得以体现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值