题意:电梯每层有一个不同的数字,例如第n层有个数字k,那么这一层只能上k层或下k层,但是不能低于一层或高于n层,给定起点与终点,要求出最少要按几次键。
分析:很不错的一道题。可以搜索,也可以spfs。把每层电梯当作一个点,只要在范围内,最多可以有两条边,边的权值为1。
SPFA
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstring>
#include<cstdio>
#include<map>
const int INF=0x3f3f3f3f;
typedef long long LL;
using namespace std;
const int maxn=10055;
struct Edge
{
int e,w;
Edge(){}
Edge(int _e,int _w):e(_e),w(_w){}
};
int dist[maxn];
vector<Edge> G[maxn];
int N,A,B;
int spfa(int v,int e)
{
for(int i=0;i<maxn;i++) dist[i]=INF;
queue<int> q;
dist[v]=0;
q.push(v);
while(!q.empty())
{
int s=q.front();q.pop();
for(int i=0;i<G[s].size();i++)
{
int e=G[s][i].e;
if(dist[e]>dist[s]+G[s][i].w)
{
dist[e]=dist[s]+G[s][i].w;
q.push(e);
}
}
}
return dist[e];
}
int main()
{
// freopen("E:\\ACM\\test.txt","r",stdin);
while(cin>>N>>A>>B)
{
int x;
for(int i=0;i<=N;i++) G[i].clear();
for(int i=1;i<=N;i++)
{
cin>>x;
if(i+x<=N) G[i].push_back(Edge(i+x,1));
if(i-x>=1) G[i].push_back(Edge(i-x,1));
}
int ans=spfa(A,B);
if(ans==INF) puts("-1");
else cout<<ans<<endl;
}
return 0;
}
BFS
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
const int INF=0x3f3f3f3f;
typedef long long LL;
using namespace std;
const int maxn=10055;
struct node
{
int d; //当前的层数
int step; //步数
node(int _d,int _step):d(_d),step(_step){}
};
int vis[maxn];
int a[maxn];
int N,A,B;
int bfs()
{
memset(vis,0,sizeof(vis));
queue<node>q;
q.push(node(A,0));
vis[A]=1;
while(!q.empty())
{
node s=q.front();q.pop();
if(s.d==B) return s.step;
for(int i=-1;i<=1;i+=2)
{
int nd=s.d+i*a[s.d];
if(nd>=1&&nd<=N&&!vis[nd])
{
q.push(node(nd,s.step+1));
vis[nd]=1;
}
}
}
return -1;
}
int main()
{
// freopen("E:\\ACM\\test.txt","r",stdin);
while(cin>>N>>A>>B)
{
for(int i=1;i<=N;i++) cin>>a[i];
cout<<bfs()<<endl;
}
return 0;
}