Description
期末考试终于结束了。Andy同学感觉松了一口气,他决定重温小时候的快乐时光–下飞行棋。但是他弄丢了传统飞行棋需要的骰子,因此他发明了一种新型的飞行棋游戏,规则如下:棋盘上有n个格子,由近到远分别编号为1到n。对于1≤i≤n,第i个格子上写着一个正整数Ni。当玩家处于第a个格子时,他可以选择往后走Na步,或者往前倒退Na步。当然如果Na+a>n,那么他就只能选择后退;同理如果a−Na<1,那么他就只能选择前进。保证不会出现既不能前进又不能后退的格子。
Andy学完编程后对一个问题很感兴趣:从编号s出发,至少需要经过几把,可以到达t点?(例如在a点选择往前走Na步,称之为一把)。
Input
第一行三个整数,分别为n,s,t意义如题面所述。
第二行n个正整数,第i个数为Ni。
Output
一个数,为最少经过的把数。如果s无法到达t,输出-1。
Input
6 6 4
1 2 2 3 1 2
Output
1
Hint
对于前10%的数据,s=t;
对于前40%的数据,n≤200;
对于另外10%的数据,s无法到达t;
对于100%的数据,n≤200000;
# include<iostream>
# include<queue>
using namespace std;
const int MAX=2e5+5;
struct node{
int dis;
int num;
};
queue<node>q;
int n,s,t;
int a[MAX],vis[MAX];
inline int read(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void bfs(){
while(!q.empty()){
node p=q.front();
if(p.dis == t) {
cout<< p.num ;
return ;
}
int dis1=p.dis+a[p.dis];
if(dis1<=n&&!vis[dis1]){
q.push({dis1,p.num+1});
vis[dis1]=1;
}
int dis2=p.dis-a[p.dis];
if(dis2>=1&&!vis[dis2]){
q.push({dis2,p.num+1});
vis[dis2]=1;
}
q.pop();
}
cout<<-1;
return ;
}
int main(){
n=read();s=read();t=read();
for(int i=1;i<=n;++i)
a[i]=read();
if(n==t) {
cout<<0;
return 0;
}
q.push({s,0});
vis[s]=1;
bfs();
return 0;
}