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++ ,