洛谷P1135 奇怪的电梯

本文介绍了一个基于电梯楼层数字进行移动的有趣问题,并采用SPFA算法求解从A楼到B楼所需的最少按键次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

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

输入输出格式

输入格式:

输入文件共有二行,第一行为三个用空格隔开的正整数,表示N,A,B(1≤N≤200, 1≤A,B≤N),第二行为N个用空格隔开的非负整数,表示Ki。

输出格式:

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

输入输出样例

输入样例#1: 
5 1 5
3 3 1 2 5
输出样例#1: 
3
看的像个搜索。。。
实际上是个@¥%#¥#@¥spfa。。。

附代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#define MAXN 210
#define MAX 999999999
using namespace std;
int n,s,t,c=1,head[MAXN],path[MAXN];
bool vis[MAXN];
struct node{
	int next,to,w;
}a[MAXN<<1];
inline int read(){
	int date=0,w=1;char c=0;
	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
	return date*w;
}
inline int relax(int u,int v,int w){
	if(path[v]>path[u]+w){
		path[v]=path[u]+w;
		return 1;
	}
	return 0;
}
inline void add(int u,int v,int w){
	a[c].to=v;a[c].w=w;
	a[c].next=head[u];
	head[u]=c++;
}
void spfa(){
	int u,v;
	queue<int> q;
	for(int i=1;i<=n;i++){path[i]=MAX;vis[i]=false;}
	path[s]=0;
	vis[s]=true;
	q.push(s);
	while(!q.empty()){
		u=q.front();
		q.pop();
		vis[u]=false;
		for(int i=head[u];i;i=a[i].next){
			v=a[i].to;
			if(relax(u,v,a[i].w)&&!vis[v]){
				vis[v]=true;
				q.push(v);
			}
		}
	}
	printf("%d\n",path[t]==MAX?-1:path[t]);
}
int main(){
	n=read();s=read();t=read();
	for(int i=1;i<=n;i++){
		int x=read();
		if(i+x<=n)add(i,i+x,1);
		if(i-x>=1)add(i,i-x,1);
	}
	spfa();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值