题目:
小S是一个爱锻炼的孩子,他在放假期间坚持在A公园练习跑步。
但不久后,他就开始为在重复的地点练习感到厌烦了,他就打算去B公园跑步。
但是小S由于没有去过B公园,他不知道B公园是否适合练习跑步,又不知道在B公园怎样跑是最优的。所以小S就去B公园进行了一番勘测。
小S在进行了一番勘测后,画出了一张地图,地图每一个位置上都辨识了小S到达该位置后不能往哪一个方位移动。其中有5种表示的符号:“U”代表不能向上移动,“D”代表不能向下移动,“L”代表不能向左移动,“R”代表不能向右移动,如果该位置有障碍物,小S到达那里后无法继续训练,就用“S”来代表。整个公园共有n行m列,小S会从第1行第1列出发,到第n行第m列结束他的练习。
现在小S想要知道,从起点(即第1行第1列)到终点(第n行第m列),途中最少要改变几次方向(即上一次移动的方向和这一次移动的方向不一样)?
注意:小S如在训练途中离开公园(即地图范围),则算是结束训练。
解题思路:
裸的广搜
Accepted code:
#include<queue>
#include<cstdio>
using namespace std;
const int dx[5] = {0, -1, 1, 0, 0}, dy[5] = {0, 0, 0, -1, 1};
int n, m, b[551][551], a[551][551];
bool g[551][551];
void bfs() {
queue<int> x, y, dis;
x.push(1); y.push(1); dis.push(-1);
while (x.size()) {
int x1 = x.front(), y1 = y.front();
if (a[x1][y1] != -1)
for (int i = 1; i <= 4; i++) {
int k = 0;
while (1) {
k++;
int X = x1 + k * dx[i], Y = y1 + k * dy[i];
if (X < 1 || Y < 1 || X > n || Y > m) break;
if (a[X][Y] == -1 || a[X - dx[i]][Y - dy[i]] == i) break;
if (g[X][Y]) continue;
g[X][Y] = 1;
x.push(X); y.push(Y);
dis.push(dis.front() + 1);
if (X == n && Y == m) {
printf("%d", dis.front() + 1);
return;
}
}
}
x.pop(); y.pop(); dis.pop();
}
printf("No Solution");
}
int main() {
scanf("%d%d", &n, &m); getchar();
for (int i = 1; i <= n; i++, getchar())
for (int j = 1; j <= m; j++) {
char c = getchar();
if (c == 'U') a[i][j] = 1;
if (c == 'D') a[i][j] = 2;
if (c == 'L') a[i][j] = 3;
if (c == 'R') a[i][j] = 4;
if (c == 'S') a[i][j] = -1;
}
a[n][m] = 0;
bfs();
}