POJ 3083 BFS(一)

2014-11-24 11:05:32 · 作者: · 浏览: 0

题目大意: 说有一个迷宫,迷宫有一个入口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
#include
#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(c