POJ3984 迷宫问题

问题链接POJ3984 迷宫问题

问题简述:参见上述链接。

问题分析迷宫问题是一个经典的搜索问题,如果是求出一个解,问题就简单很多,通常用DFS来实现。然而,本问题是求路径最短的解,即步数最少的解,就需要用BFS了。

程序说明使用C语言编写程序的话,处理起来略微复杂一些,需要另外写一个程序。

这里使用C++语言编程,并且使用STL的队列queue,程序简洁。

几个要点说明如下:

1.宏定义 使用宏定义可以增强程序的通用性。类似的问题可以通过修改宏定义来实现,而不需要修改程序。

2.方向数组 使用方向数组后,各个方向的试探的程序就会变得简洁了。

3.父节点矩阵 在节点搜索过程中,使用父节点矩阵(二维数组)father[][]。其目的是保证搜索到结果时,能够方便地输出结果,否则很难处理。father[][]中,每个元素都指向其父节点。

4.避免重复搜索 将搜索过的节点设置为“墙”,可以避免重复搜索,也能够简化程序逻辑。

5.设置边界 通过设置边界,可以免去矩阵(二维数组)的边界判断,简化了程序逻辑。由于增加边界使得数组下标做了映射,在输出结果时需要做相应的调整。

AC的C++语言程序如下:

/* POJ3984 迷宫问题 */

#include <cstdio>
#include <queue>

using namespace std;

#define MAXN 5

#define STARTROW 1
#define STARTCOL 1
#define ENDROW MAXN
#define ENDCOL MAXN

#define DIRECTSIZE 4

struct direct {
    int drow;
    int dcol;
} direct[DIRECTSIZE] = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}};

int maze[MAXN+2][MAXN+2];

struct node {
    int row;
    int col;
};

node father[MAXN+2][MAXN+2];

queue<node> q;

void print_result()
{
    node path[MAXN*MAXN];
    int count = 0;

    // 逆序搜索,放入路径数组中
    path[count].row = ENDROW;
    path[count].col = ENDCOL;
    for(;;) {
        if(path[count].row == STARTROW && path[count].col == STARTCOL)
            break;

        path[count+1] = father[path[count].row][path[count].col];
        count++;
    }

    // 顺序输出结果
    while(count >= 0) {
        printf("(%d, %d)\n", path[count].row-1, path[count].col-1);

        count--;
    }
}

void bfs()
{
    node start; // 设置起始节点
    start.row = STARTROW;
    start.col = STARTCOL;
    q.push(start);

    while(!q.empty()) {
        node front = q.front(); q.pop();
        if (front.row == ENDROW && front.col == ENDCOL) {
            print_result();
            return;
        }
        for(int i=0; i<DIRECTSIZE; i++) {
            int nextrow = front.row + direct[i].drow;
            int nextcol = front.col + direct[i].dcol;
            if(maze[nextrow][nextcol] == 0) {
                father[nextrow][nextcol] = front;
                node v;
                v.row = nextrow;
                v.col = nextcol;
                q.push(v);
            }
        }

        maze[front.row][front.col] = 1; // 搜索过的节点不再搜索
    }
}

int main(void)
{
    int i, j;
    for(i=0; i<MAXN+2; i++) {
        maze[0][i] = 1;
        maze[MAXN+1][i] = 1;
        maze[i][0] = 1;
        maze[i][MAXN+1] = 1;
    }

    // 输入数据
    for(i=1; i<=MAXN; i++)
        for(j=1; j<=MAXN; j++)
            scanf("%d", &maze[i][j]);

    // 广度优先搜索
    bfs(); // 开始搜索

    return 0;
}







 

posted on 2016-07-11 08:16  海岛Blog  阅读(144)  评论(0编辑  收藏  举报

导航