P1135 奇怪的电梯(DFS or BFS)

题目描述

呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第 i 层楼(1≤i≤N)上有一个数字 Ki​(0≤Ki​≤N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如: 3,3,1,2,53,3,1,2,5 代表了 Ki​(K1​=3,K2​=3,……),从 1 楼开始。在 1 楼,按“上”可以到 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

 解题思路:DFS加剪枝

  1. 是否越界;

  2. 这个位置是否之前抵达过且比现在抵达的次数要早;

  3. 当前的次数是否超过了目前的答案。

#include<iostream>
using namespace std;
const int N=210;
int n,a,b,arr[N],minn[N],ans=1e8;
void dfs(int a,int b,int p)
{
    if(a<1||a>n) //不符合范围,进行剪枝
    {
        return;
    }
    if(p>=minn[a]) //当前到达慢与之前的,进行剪枝
    {
        return;
    }
    if(p>=ans) //当前次数大于原有答案,进行剪枝
    {
        return;
    }
    if(a==b) //找到答案
    {
        ans=p;
        return;
    }
    minn[a]=p; //更新到达这个点的最小次数
    dfs(a+arr[a],b,p+1);
    dfs(a-arr[a],b,p+1);
}
int main()
{
    cin>>n>>a>>b;
    for(int i=1;i<=n;i++)
    {
        cin>>arr[i];
        minn[i]=1e8;
    }
    dfs(a,b,0);
    if(ans!=1e8)
    {
        cout<<ans;
    }
    else
    {
        cout<<"-1";
    }
    return 0;
}
//BFS解法
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int N=210;
struct xx{
    int level;
    int step;
};
int n,a,b;
int arr[N];
int vis[N]; //标记数组
void bfs()
{
    xx cur,nex;
    cur.level=a;
    cur.step=0;
    queue<xx> s;
    s.push(cur);
    vis[a]=1;
    while(!s.empty())
    {
        cur=s.front();
        s.pop();
        if(n==0)
        {
            printf("-1");
            return;
        }
        if(cur.level==b)
        {
            printf("%d",cur.step);
            return;
        }
        nex.level=cur.level+arr[cur.level];
        nex.step=cur.step+1;
        if(nex.level<=n)
        {
            if(vis[nex.level]==0)
            {
                vis[nex.level]=1; //标记来过
                s.push(nex);
            }
        }
        nex.level=cur.level-arr[cur.level];
        nex.step=cur.step+1;
        if(nex.level>=1)
        {
            if(vis[nex.level]==0)
            {
                vis[nex.level]=1; //标记来过
                s.push(nex);
            }
        }
    }
    printf("-1");
    return;
}
int main()
{
    cin>>n>>a>>b;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&arr[i]);
        vis[i]=0; //每层楼没来过
    }
    bfs();
    return 0;
}

  • 48
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值