题目链接

https://www.luogu.com.cn/problem/P1135
(来自洛谷)

题目大意

n层电梯(1<=n<=200),每个电梯有个k值,代表乘坐此电梯可以到达n+k层和n-k层,当然,这必须要保证n+k层和n-k层存在,不存在是无法到达的。问最少摁多少次电梯按钮能从指定电梯到指定电梯。

解题思路

bfs,显而易见。(学长讲题的时候说是板子,我没做出来,好烦!)
但是自己写的时候并没有想到如何更新cnt的值(cnt用于记录是摁了第几次按钮),因为bfs的时候并不知道哪个是根,哪个是延伸出来的子节点,所以最后只过了50的数据。
正解是建立一个cnt数组,cnt[i]表示第i层的电梯是第几次摁的,cnt[i]值的刷新是i的父亲电梯的cnt值+1得到的。因此,只要碰到目标电梯,直接输出并return即可。
(确实挺板子的,但是实在没想出来cnt变化该怎么存储,哎菜鸡叹息
其实,本质考察的就是图,有向图。

AC代码

#include<bits/stdc++.h>
using namespace std;
const int N=205;
int a,b,n;
int vis[N];//一定别忘了标记已访问过的电梯!!!
vector<int> v[N];//存路径
int cnt[N];
void bfs(int x){
    queue<int> q;
    q.push(x);
    while(!q.empty()){
        int tmp=q.front();
        q.pop();
        for(int i=0;i<v[tmp].size();i++){
            int next=v[tmp][i];
            if(vis[next]) continue;
            vis[next]=1;
            cnt[next]=cnt[tmp]+1;//与板子题,只差这一句
            q.push(next);
            if(next==b) {cout<<cnt[next]<<endl;return ;}
        }        
    }
    cout<<-1<<endl;
    return ;    
}
int main(){
    int k;
    cin>>n>>a>>b;
    for(int i=1;i<=n;i++){
        cin>>k;
        if(i-k>0) v[i].push_back(i-k);//要是第i个电梯能向下走k层,那么可以从i到i-k层,存下有向边
        if(i+k<=n) v[i].push_back(i+k);//要是第i个电梯能向上走k层,那么可以从i到i+k层,存下有向边
    }
    if(a==b){cout<<0<<endl;return 0;}//一定要特判一下(按我这方法的话),这个特判我也没想到(差一组样例,懒得debug了,直接下载的数据,其实这样做是不利于进步的!不建议模仿QAQ)

    vis[a]=1;//勿忘
    bfs(a);
}