P1135 奇怪的电梯 题解
wangjue1629 · · 题解
Solution
题目传送门
题目分析
我们要计算从起始楼层 -1。
题目思路
这道题我一开始是用的 DFS 做的,但是后来发现 BFS 更好。
使用 BFS 是因为我们需要找到最短路径。BFS 适合于在未加权的图中寻找最短路径。 从起始楼层开始,将其添加到队列中。
解题步骤
-
每次从队列中取出一个元素,并探索它可以直接达到的楼层(根据
k_i 向上或向下移动)。 -
如果某个可达的楼层是目的地,则返回到达该楼层所需的步数。如果无法到达目标楼层,返回
-1。
但是,我们还要防止重复计算,我们可以使用一个布尔数组
AC Code
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int maxn = 200 + 10;
int a[maxn];
bool vis[maxn]; //标记每层楼是否已访问
int step[maxn]; //记录到达每层楼的最小步数
//BFS 函数,计算从 st(起始楼层)到 ed(目标楼层)的最少步数
int bfs(int st, int ed, int n){
if(st == ed) return 0; //如果起始楼层和目标楼层相同,则无需移动
queue<int> q;
q.push(st); //将起始楼层加入队列
vis[st] = true; //标记起始楼层为已访问
step[st] = 0;
while(!q.empty()){
int cnt = q.front();
q.pop();
//获取队列前端的楼层,并弹出这个楼层
int up = cnt + a[cnt]; //计算向上移动的目标楼层
int down = cnt - a[cnt]; //计算向下移动的目标楼层
//检查向上移动是否可行
if(up <= n && !vis[up]){
vis[up] = true;
step[up] = step[cnt] + 1;
q.push(up); //将新楼层加入队列
if(up == ed){ //如果达到目标楼层,返回步数
return step[up];
}
}
//检查向下移动是否可行
if(down >= 1 && !vis[down]){
vis[down] = true;
step[down] = step[cnt] + 1;
q.push(down); //将新楼层加入队列
if(down == ed){ //如果达到目标楼层,返回步数
return step[down];
}
}
}
return -1; //如果无法到达目标楼层,返回 -1
}
int main(){
int n, st, ed;
cin >> n >> st >> ed;
for(int i = 1; i <= n; i++){
cin >> a[i];
}
memset(vis, false, sizeof(vis));
int result = bfs(st, ed, n);
cout << result << endl;
return 0;
}
时间复杂度: