洛谷———奇怪的电梯,BFS的典型

思路分析

电梯的上下可以看作是两个方向的运动,题目中要求最短的路径,那么优先考虑BFS(广度优先搜索)。结合连表结构就可以解决问题。

https://www.luogu.com.cn/problem/P1135icon-default.png?t=N7T8https://www.luogu.com.cn/problem/P1135

代码解析

定义部分

首先,我们需要一个数组来记录每个楼层可以上(下)的层数;

一个布尔类型的数组来记录楼层是否被访问;

储存现在楼层的fn  (floor now);

一个结构体来记录实时的楼层变化和按按钮的次数;

int a[205];
bool ch[205];
int fn;
struct flor{
	int i;//记录楼层
	int s;//记录步数
};
flor flr[205];

准备部分

准备部分主要初始化队列,并准备好接下所要用到数组等

memset(ch,0,sizeof(ch));//别忘记归零
	int n,A,B;
	cin>>n>>A>>B;
	if(A==B) //起始楼层与终点楼层相同时不需要按按钮
	{
		cout<<0;
		return 0;//输出后立即终止程序
	}
	for(int i=1;i<=n;i++)
		cin>>a[i];
	int head=1,
		tail=2;
	flr[head].i=A;
	flr[head].s=0;
	//标记头尾及元素值
	int flag=0;//用来记录是否到达终点楼层
	int updown[2];//储存上下的层数

主体部分

从两个方向出发,广度搜索楼层,第一个到达的就是最短路径

队列不为空时进入循环,当某时刻队列为空时,表示穷途末路输出-1并结束程序

下面的代码中注释了两条输出函数,代码出错时可以取消注释,运行后找出问题(调试)

while(tail>head)//队列不为空时进入循环
	{
		updown[0]=a[flr[head].i];
		updown[1]=-a[flr[head].i];
		for(int i=0;i<2;i++)
		{
			fn=flr[head].i+updown[i];//cout<<"*"<<fn<<endl;代码出错时可以取消注释,来调试
			if(fn<1||fn>n||ch[fn]==1) continue;
			//cout<<fn<<endl;不带*的表示已经满足if的条件
			flr[tail].i=fn;//将该楼层放入队列
			flr[tail].s=flr[head].s+1;//步数在父亲的基础上加一
			ch[fn]=1;//标记楼层已被访问
			tail++;//准备添加队列成员
			if(fn==B)//判断是否到达
			{
				flag=1;
				break;
			}	
		}
		if(flag==1) break;
		head++;
		if(tail<=head)//队列为空时表示现在已经无路可走
		{
			cout<<-1;
			return 0;
		}
    }
	cout<<flr[tail-1].s;
	return 0;

代码展示

理清思路,多上手尝试,连贯就不是问题

​
#include<bits/stdc++.h>
using namespace std;
int a[205];
bool ch[205];
int fn;
struct flor{
	int i;//记录楼层
	int s;//记录步数
};
flor flr[205];
int main()
{
	memset(ch,0,sizeof(ch));//别忘记归零
	int n,A,B;
	cin>>n>>A>>B;
	if(A==B) //起始楼层与终点楼层相同时不需要按按钮
	{
		cout<<0;
		return 0;//输出后立即终止程序
	}
	for(int i=1;i<=n;i++)
		cin>>a[i];
	int head=1,
		tail=2;
	flr[head].i=A;
	flr[head].s=0;
	//标记头尾及元素值
	int flag=0;//用来记录是否到达终点楼层
	int updown[2];//储存上下的层数
	while(tail>head)//队列不为空时进入循环
	{
		updown[0]=a[flr[head].i];
		updown[1]=-a[flr[head].i];
		for(int i=0;i<2;i++)
		{
			fn=flr[head].i+updown[i];//cout<<"*"<<fn<<endl;代码出错时可以取消注释,来调试
			if(fn<1||fn>n||ch[fn]==1) continue;
			//cout<<fn<<endl;不带*的表示已经满足if的条件
			flr[tail].i=fn;//将该楼层放入队列
			flr[tail].s=flr[head].s+1;//步数在父亲的基础上加一
			ch[fn]=1;//标记楼层已被访问
			tail++;//准备添加队列成员
			if(fn==B)//判断是否到达
			{
				flag=1;
				break;
			}	
		}
		if(flag==1) break;
		head++;
		if(tail<=head)//队列为空时表示现在已经无路可走
		{
			cout<<-1;
			return 0;
		}
    }
	cout<<flr[tail-1].s;
	return 0;
}

​

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值