zoukankan      html  css  js  c++  java
  • 迷宫问题

    队列也是一组元素的集合,也提供两种基本操作:Enqueue(入队)将元素添加到队尾,Dequeue(出队)从队头取出元素并返回。就像排队买票一样,先来先服务,先入队的人也是先出队的,这种方式称为FIFO(First In First Out,先进先出),有时候队列本身也被称为FIFO。

    下面我们用队列解决迷宫问题。程序如下:(参考《linux c 编程一站式学习》)

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
     
    /*************************************************************************
    > File Name: breadth_search.c
    > Author: Simba
    > Mail: dameng34@163.com
    > Created Time: 2012年12月24日 星期一 19时24分37秒
    ************************************************************************/

    #include<stdio.h>


    #define MAX_ROW 5
    #define MAX_COL 5

    struct point
    {
        int row, col, predecessor;
    } queue[512];

    int head = 0, tail = 0;

    void enqueue(struct point p)
    {
        queue[tail++] = p;
    }

    struct point dequeue(void)
    {
        return queue[head++];
    }

    int is_empty(void)
    {
        return head == tail;
    }

    int maze[MAX_ROW][MAX_COL] =
    {
        {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},
    };

    void print_maze(void)
    {
        int i, j;
        for (i = 0; i < MAX_ROW; i++)
        {
            for (j = 0; j < MAX_COL; j++)
                printf("%d ", maze[i][j]);
            putchar(' ');
        }
        printf("********* ");
    }

    void visit(int row, int col)
    {
        struct point visit_point = { row, col, head - 1 };
        maze[row][col] = 2;
        enqueue(visit_point);
    }

    int main(void)
    {
        struct point p = { 0, 0, -1 };

        maze[p.row][p.col] = 2;
        enqueue(p);

        while (!is_empty())
        {
            p = dequeue();
            if (p.row == MAX_ROW - 1    /* goal */
                    && p.col == MAX_COL - 1)
                break;
            if (p.col + 1 < MAX_COL /* right */
                    && maze[p.row][p.col + 1] == 0)
                visit(p.row, p.col + 1);
            if (p.row + 1 < MAX_ROW /* down */
                    && maze[p.row + 1][p.col] == 0)
                visit(p.row + 1, p.col);
            if (p.col - 1 >= 0  /* left */
                    && maze[p.row][p.col - 1] == 0)
                visit(p.row, p.col - 1);
            if (p.row - 1 >= 0  /* up */
                    && maze[p.row - 1][p.col] == 0)
                visit(p.row - 1, p.col);
            print_maze();
        }
        if (p.row == MAX_ROW - 1 && p.col == MAX_COL - 1)
        {
            printf("(%d, %d) ", p.row, p.col);
            while (p.predecessor != -1)
            {
                p = queue[p.predecessor];
                printf("(%d, %d) ", p.row, p.col);
            }
        }
        else
            printf("No path! ");

        return 0;
    }

    输出为:


    其实仍然可以像《用深度优先搜索解迷宫问题》一样用predecessor数组表示每个点的前趋,但我们可以换一种更方便的数据结构,直接在每个点的结构体中加一个成员表示前趋:
    struct point { int row, col, predecessor; } queue[512];

    int head = 0, tail = 0;
    变量head和tail是队头和队尾指针,head总是指向队头,tail总是指向队尾的下一个元素。每个点的predecessor成员也是一个指针,指向它的前趋在queue数组中的位置。如下图所示:


    这是一个静态分配的数组,每个数组元素都有row、col和predecessor三个成员,predecessor成员保存一个数组下标,指向数组中的另一个元素,这其实也是链表的一种形式,称为《静态链表》。

    为了帮助理解,把这个算法改写成伪代码如下图:


    从打印的搜索过程可以看出,这个算法的特点是沿各个方向同时展开搜索,每个可以走通的方向轮流往前走一步,这称为广度优先搜索(BFS,Breadth First Search)。探索迷宫和队列变化的过程如下图所示。


    广度优先是一种步步为营的策略,每次都从各个方向探索一步,将前线推进一步,图中的虚线就表示这个前线,队列中的元素总是由前线的点组成的,可见正是队列先进先出的性质使这个算法具有了广度优先的特点。广度优先搜索还有一个特点是可以找到从起点到终点的最短路径,而深度优先搜索找到的不一定是最短路径。

  • 相关阅读:
    【杭电】[4883]TIANKENG’s restaurant
    【杭电】[4883]TIANKENG’s restaurant
    【POJ】[1423]Big Number
    【POJ】[1423]Big Number
    【杭电】[1280]前m大的数
    【杭电】[1280]前m大的数
    【杭电】[1576]A/B
    【杭电】[1576]A/B
    [leetcode]346. Moving Average from Data Stream滑动窗口平均值
    [leetcode]99. Recover Binary Search Tree恢复二叉搜索树
  • 原文地址:https://www.cnblogs.com/alantu2018/p/8471672.html
Copyright © 2011-2022 走看看