程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> POJ 3083 BFS

POJ 3083 BFS

編輯:C++入門知識

題目大意: 說有一個迷宮,迷宮有一個入口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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved