当前位置:编程学习 > C/C++ >>

POJ 3083 BFS

题目大意: 说有一个迷宫,迷宫有一个入口S和出口E,现在要你求出三种路径各自的长度

1. 沿着最左边走。

2. 沿着最右边走。

3. 最短路径。

其实沿着最左,最右方向走的时候,特别需要小心的是考虑在顺时针和逆时针转的时候,当前方向,选择下一个位置,和下一个方向之间的关系。

为了更好的解释,我用图说明一下:

 

1. 沿着最左边走:
当沿着最左边缘的墙壁行走的时候,每次搜索的方向都是从当前方向的左边,然后按照逆时针的方向进行搜索的。

不妨我们将搜索的四个点用数组表示 SearchDirection: (0, -1), (1,0), (0, 1), (-1, 0).


假如当前遍历的 点是(r,c).

假设当前行走方向是 UP,那么对应最左是 SearchDirection[0], 按照合法性搜索 0, 1, 2, 3;

如果当前行走方向是RIGHT, 那么最左是SearchDirection[1], 合法搜索方向是 1, 2, 3, 0.

                                    DOWN,                        SearchDirection[2],                               2, 3, 1, 0

                                    LEFT                            SearchDirection[3],                              3, 0, 1, 2


根据初始方向容易决定搜索方向和搜索起始点,但是如何决定搜索以后的下一个方向呢。

如果当前选择了, SearchDirection[0] -> 则对应最后的LEFT

                              SearchDirection[1] -> UP

                              SearchDirection[2] -> RIGHT

                              SearchDirection[3] -> DOWN

假设初始方向是  enum {UP, RIGHT, DOWN, LEFT} 表示的 d, 选择的searchDirection是 i,那么最后的方向就是 dNew  = i + 3;


对于逆时针有类似的属性。


关于最短路径这里,也有一些想法吧,最开始用DFS做了一下,发现结果超时了。

后来用BFS做了一下,就AC了。


其实做了几个题目以后,个人感觉可达性问题是比较适合用DFS解决的,而最短路径就比较适合用BFS解决。

提到最短路径就时常会想起 Dijkstra,这个算法是解决单源最短路径的经典算法,不过它针对的是更通用的问题,就是说每个边的权重是一个整数,并且没有负数环。

而这里问题是很简单的,根据两点的拓扑可达性,距离只有0 和 1,所以利用BFS解决是更合理的方法。

在DFS中,回溯过程会所搜索很多空间,并不适合求最短路径。而BFS因为在求解的过程中,将遍历的过的节点不再继续遍历,所以会有比较高的效率。


代码如下:

[cpp] 
#include <stdio.h> 
#include <memory.h> 
#define MAX_GRID 45 
 
struct Grid 

    int r; 
    int c; 
 
    int nSteps; 
 
    Grid(int _r, int _c) 
    { 
        r = _r; 
        c = _c; 
        nSteps = 0; 
    } 
    Grid() 
    { 
        nSteps = 0; 
    } 
}; 
 
bool operator == (const Grid&a, const Grid &b) 

    return a.r == b.r && a.c == b.c; 

bool operator != (const Grid &a,const Grid&b) 

    return (a.r != b.r) || (a.c != b.c); 

 
Grid g_Neighbors[4] =  
{ Grid(0, -1), Grid(-1,0), Grid(0, 1), Grid(1, 0) 
}; 
 
enum Direction{UP = 0, RIGHT, DOWN, LEFT}; 
int g_Yard[MAX_GRID][MAX_GRID]; 
int nCol, nRow; 
 
Grid GetNewPoint(const Grid ¤tGrid, int iNeighbor) 

    Grid g = Grid(currentGrid.r + g_Neighbors[iNeighbor].r, currentGrid.c + g_Neighbors[iNeighbor].c); 
    return g; 

void GetLeftMost(const Grid ¤tGrid, Direction d, Grid &nextGrid, Direction &nextdirection ) 

    int iStart = (int)d; 
    Grid g; 
    for( int i = 0; i < 4; i++) 
    { 
        g = GetNewPoint(currentGrid, (iStart + i)%4); 
        if(g_Yard[g.r][g.c] == 1) 
        { 
            continue; 
        } 
        else 
        { 
            nextGrid = g; 
            nextdirection = Direction(((int)d + i + 3)%4); 
            break; 
        } 
    } 

void GetRightMost(const Grid ¤tGrid, Direction d, Grid &nextGrid, Direction &nextdirection) 

    int iStart = ((int)d + 2)%4; 
 
    Grid g; 
 
    for( int i = 4; i > 0; i--) 
    { 
        g = GetNewPoint(currentGrid, (iStart + i)%4); 
        if(g_Yard[g.r][g.c] == 1) 
        { 
            continue; 
        } 
        else 
        { 
            nextGrid = g; 
            nextdirection = Direction(((int)d + i + 1)%4); 
            break; 
        } 
 
    } 
 

 
Direction GetInitialDirection(const Grid &start) 

    if(start.r == 0) 
    { 
  &nbs

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,