POJ 3083 BFS

来源:互联网 发布:mac能玩魔兽世界 编辑:程序博客网 时间:2024/06/06 08:52

题目地址:http://poj.org/problem?id=3083

题目大意: 说有一个迷宫,迷宫有一个入口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因为在求解的过程中,将遍历的过的节点不再继续遍历,所以会有比较高的效率。


代码如下:

#include <stdio.h>#include <memory.h>#define MAX_GRID 45struct 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;}



原创粉丝点击