题目
定义一个二维数组:
int maze[5][5] = {
0,1,0,0,0,
0,1,0,1,0,
0,0,0,0,0,
0,1,1,1,0,
0,0,0,1,0,
};
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。
输入
一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。
输出
左上角到右下角的最短路径,格式如样例所示。
样例
输入
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
输出
(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)
思路
之前的思路是用二维数组记录走到每一点所用步数, 根据BFS找到结果就退出的特性, 只存在一条路径从起点到终点满足递增, 可以像DP求方案那样逆推一遍得到。
逆推的操作可以使用DFS。
这里是把用来记录是否走过的数组bool st[][]
扩展为 pair<int,int> prev[][]
, 即每个格子是从哪个格子走过来的。
代码
const int N = 6;
int g[N][N];
typedef pair<int, int> PII;
PII prevs[N][N];
PII q[N * N];
int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1};
void bfs(int xx, int yy)
{
int hh = 0, tt = 0;
q[0] = {xx, yy};
prevs[xx][yy] = {-1, -1};
while (hh <= tt)
{
auto t = q[hh++];
int x = t.first, y = t.second;
if (x == 1 && y == 1)
return;
for (int i = 0; i < 4; i++)
{
int a = x + dx[i], b = y + dy[i];
if (a < 1 || a > 5 || b < 1 || b > 5 || g[a][b])
continue;
if (prevs[a][b].first == 0 && prevs[a][b].second == 0)
{
q[++tt] = {a, b};
prevs[a][b] = {x, y};
}
}
}
}
void print_ans(int x, int y)
{
if (x == -1 && y == -1)
return;
print_ans(prevs[x][y].first, prevs[x][y].second);
printf("(%d, %d)\n", x - 1, y - 1);
}
int main()
{
for (int i = 1; i <= 5; i++)
{
for (int j = 1; j <= 5; j++)
{
cin >> g[i][j];
}
}
bfs(5, 5);
PII end(1, 1);
while (true)
{
printf("(%d, %d)\n", end.first - 1, end.second - 1);
if (end.first == 5 && end.second == 5)
break;
end = prevs[end.first][end.second];
}
return 0;
}