HOJ 1180 诡异的楼梯

本题在bfs的基础上需要考虑多一点东西,就是题目中的楼梯变化。
下面是我个人觉得要注意到的:

  1. 梯子的改变要注意,思路明白就行
  2. 可以在梯子前等待,这是我在做的时候没有考虑到的,看了其他博主的分享后才想明白的

附这一题一篇我参考的博客,有测试数据,想找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;
}

猜你喜欢

转载自blog.csdn.net/qq_44724908/article/details/104026306