POJ 3083 BFS

来源:岁月联盟 编辑:exp 时间:2012-08-12

题目大意: 说有一个迷宫,迷宫有一个入口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) 
    { 
        return DOWN; 
    } 
    if(start.r == nRow - 1) 
    { 
        return UP; 
    } 
    if(start.c == 0) 
    { 
        return RIGHT; 
    } 
    if(start.c == nCol - 1) 
    { 
        return LEFT; 
    } 

int findStepsForLeftmost(const Grid &start, const Grid &exit) 

    Direction d = GetInitialDirection(start); 
    int nSteps = 1; 
    Grid currentGrid = start, nextGrid; 
    while( currentGrid != exit) 
    { 
        GetLeftMost(currentGrid, d,nextGrid, d); 
        currentGrid = nextGrid; 
        nSteps ++; 
    } 
    return nSteps; 
 

int findStepsForRightmost(const Grid &start, const Grid &exit) 

    Direction d = GetInitialDirection(start); 
    int nSteps = 1; 
    Grid currentGrid = start, nextGrid; 
    while( currentGrid != exit) 
    { 
        GetRightMost(currentGrid, d,nextGrid, d); 
        currentGrid = nextGrid; 
        nSteps ++; 
    } 
    return nSteps; 
 

 
 
Grid q[2000]; 
 
 
bool GridLegal(const Grid &g) 

    if( g.r < 0 || g.r >= nRow || g.c < 0 || g.c >= nCol || g_Yard[g.r][g.c] == 1) 
    { 
        return false; 
    } 
    return true; 

int BFS(const Grid &start, const Grid & exit) 

 
    int front, rear; 
    front = rear = 0; 
 
    q[rear++] = start; 
     
    while(rear > front) 
    { 
        Grid top = q[front]; 
         
        if(top == exit) 
        { 
            return top.nSteps; 
        } 
        //iterate the neighboring  
        for(int i = 0; i < 4; i++) 
        { 
            Grid neighbor = GetNewPoint(top, i); 
            if(GridLegal(neighbor))// not visited 
            { 
                g_Yard[neighbor.r][neighbor.c] = 1; 
                neighbor.nSteps = top.nSteps + 1; 
                q[rear++] = neighbor; 
            } 
        } 
 
        front++; 
    } 
    return -1; 
 

 
int main() 

 
 
    int nCase; 
    scanf("%d", &nCase); 
    while(nCase--) 
    { 
 
 
        scanf("%d%d", &nCol, &nRow); 
        int i,j; 
        char c; 
        memset(g_Yard, 0, sizeof(g_Yard)); 
        Grid start, exit; 
 
        for( i = 0; i < nRow; i++) 
        { 
            getchar(); 
 
            for( j = 0; j < nCol; j++) 
            { 
                c = getchar(); 
                if( c == '#') 
                { 
                    g_Yard[i][j] = 1; 
                } 
                else if( c == 'S') 
                { 
                    start.r = i; 
                    start.c = j; 
                    g_Yard[i][j] = 1; 
                } 
                else if( c == 'E') 
                { 
                    exit.r = i; 
                    exit.c = j; 
                } 
            } 
        } 
 
        int minSteps = 10000000; 
        int leftmost = findStepsForLeftmost(start, exit); 
        int rightmost = findStepsForRightmost(start, exit); 
 
        minSteps = BFS(start, exit); 
        printf("%d %d %d/n",leftmost ,rightmost, minSteps+1); 
 
    } 
    return 0; 

 


作者:hopeztm