本题在bfs的基础上需要考虑多一点东西,就是题目中的楼梯变化。
下面是我个人觉得要注意到的:
- 梯子的改变要注意,思路明白就行
- 可以在梯子前等待,这是我在做的时候没有考虑到的,看了其他博主的分享后才想明白的
附这一题一篇我参考的博客,有测试数据,想找WA原因的可以看一看:点这里哦
#include<iostream>
#include<queue>
using namespace std;
const int MAXN = 20 + 3, INF = 99999999;
typedef struct point {
int x, y;
}Point;
Point S, T;//起点和终点
char a[MAXN][MAXN];//地图
int vis[MAXN][MAXN][MAXN * MAXN], m, n, flag;//vis标记每个一时刻从起点到达每一个点所需要的最少时间
int dir[4][2] = { -1, 0, 1, 0, 0, -1, 0, 1 };//方向依次为:上下左右
int can(Point p) {//判断一个点是在地图上的且不是‘*’
if (p.x >= 0 && p.x < n && p.y >= 0 && p.y < m && a[p.x][p.y] != '*') return 1;
return 0;
}
void bfs() {
int time = 1, old_p = 1, new_p = 0;
queue<Point> Q;
Q.push(S);//起始点入队
while (!Q.empty()) {
Point p0 = Q.front();
Q.pop();
for (int i = 0; i < 4; i++) {
Point p;
p.x = p0.x + dir[i][0];
p.y = p0.y + dir[i][1];
if (can(p)) {
switch (a[p.x][p.y]) {
case 'T'://下一个点是终点,则直接结束,停止搜索
flag = 1;
cout << time << endl;
break;
case '.':
if (vis[p.x][p.y][time] > time) {//如果现路径到达该点的时间比已有到达该点的路径花费的时间更大,则当前路径不再继续,否则进行更新
vis[p.x][p.y][time] = time;
Q.push(p);
new_p++;
}
break;
default:
if ((i <= 1 && ((a[p.x][p.y] == '|' && time % 2 == 1) || (a[p.x][p.y] == '-' && time % 2 == 0)))
//这里的判断理清一下思路就好,我的方向数组dir是按“上下左右”的顺序放的
//故判断走的方向为“上下”即i为0或1,并且该时刻梯子方向为竖着
|| (i > 1 && ((a[p.x][p.y] == '-' && time % 2 == 1) || (a[p.x][p.y] == '|' && time % 2 == 0)))) {
//或者 走的方向为“左右”即i为2或3,并且梯子方向为横着,则进行“走梯子”
Point pp;
for (int ii = 0; ii < n * m; ii++)
vis[p.x][p.y][ii] = 0;
pp.x = p.x + dir[i][0];
pp.y = p.y + dir[i][1];
if(can(pp))
if (a[pp.x][pp.y] == 'T') {
flag = 1;
cout << time << endl;
break;
}
else if (a[pp.x][pp.y] == '.' && vis[pp.x][pp.y][time] > time) {
vis[pp.x][pp.y][time] = time;
Q.push(pp);
new_p++;
}
}//default中第一个if
else{
//else这一步很重要,题中的主人公是可以在梯子前等一等的
//题中说的是不能在梯子上停留,同时也说了可以在‘S','.','T'这三种位置停留的,这里要注意到
//增加一个“停留”的Point入队
//这里不需要增加时间判断,因为停留必定增加时间,但可能更快到达终点
Q.push(p0);
new_p++;
}
}//switch()
}//if(can(p))
}//for(int i = 0; i < 4; i++)
if (flag == 1)
break;
old_p--;
if (old_p == 0) {
old_p = new_p;
new_p = 0;
time++;
}//if(old_p == 0)
}//while(!Q.empty())
}//bfs()
int main() {
while (cin >> n >> m) {
flag = 0;
for (int i = 0; i < n; i++)
cin >> a[i];
for(int i = 0; i < n; i++)
for (int j = 0; j < m; j++) {
if (a[i][j] == 'S')
S = { i, j };
else if (a[i][j] == 'T')
T = { i, j };
}
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
for (int k = 0; k < n * m; k++)
if (i == S.x && j == S.y)
vis[i][j][0] = 0;
else
vis[i][j][k] = INF;
bfs();
}
return 0;
}