洛谷:P1135 奇怪的电梯 题解 -广度优先遍历BFS求解

题目描述

呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第 i 层楼(1≤i≤N)上有一个数字 Ki​(0≤Ki​≤N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如: 3,3,1,2,53,3,1,2,5 代表了 Ki​(K1​=3,K2​=3,……),从 11 楼开始。在 11 楼,按“上”可以到 44 楼,按“下”是不起作用的,因为没有 −2−2 楼。那么,从 A 楼到 B 楼至少要按几次按钮呢?

输入格式

共二行。

第一行为三个用空格隔开的正整数,表示 N,A,B(1≤N≤200,1≤A,B≤N)。

第二行为 N 个用空格隔开的非负整数,表示 Ki​。

输出格式

一行,即最少按键次数,若无法到达,则输出 -1

输入输出样例

输入

5 1 5
3 3 1 2 5

输出 

3

说明/提示

对于 100%100% 的数据,1≤N≤200,≤A,B≤N,0≤Ki​≤N。

本题共 1616 个测试点,前 1515 个每个测试点 66 分,最后一个测试点 1010 分。

这题其实就是相当用BFS广度优先遍历求最短路问题。

上代码:

#include
using namespace std;
const int N = 210;
int a[N], q[N], g[N]; //q用来表示队列,g用来存储没一层楼所需要按的最少次数
bool d[N]; //d用来标记每层楼是否被搜过
int A, B, n;
int bfs()
{
	int hh = 0, tt = 1;
	while (hh <= tt)
	{
		int k = q[hh++];
		int down = k - a[k]; //down表示按了下之后对应的层数
		int up = k + a[k];   //up表示按了上之后对应的层数
		if (down >= 1 && !d[down])  //如果层数大于1并且之前没有来过
		{
			g[down] = g[k] + 1;   //那么这层楼最少要按的次数在原有的基础上+1
			d[down] = true;       //标记该层已经来过
			q[tt++] = down;       //将这一层入队
		}
		if (up <= 200 && !d[up])  //如果该层存在且没有来过
		{ 
			g[up] = g[k] + 1;    //同上
			d[up] = true;
			q[tt++] = up;
		}
	}
	return g[B];  //返回到达B要按的次数
}
int main()
{
	cin>>n >> A >> B;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
	}
	memset(g, -1, sizeof g);
	q[0] = A; //对头首先表示在A层
	g[A] = 0; //A层到A层次数为0
	d[A] = true; //标记A层已经来过
	int u = bfs();
	cout << u << endl;
	return 0;
}

广度优先遍历BFS求解最短路问题。

算法小白的刷题日记。

你可能感兴趣的:(宽度优先,算法,数据结构,c++)