奇怪的电梯
题目描述
呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第ii层楼(1 \le i \le N)(1≤i≤N)上有一个数字K_i(0 \le K_i \le N)Ki(0≤Ki≤N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:3, 3 ,1 ,2 ,53,3,1,2,5代表了K_i(K_1=3,K_2=3,…)Ki(K1=3,K2=3,…),从11楼开始。在11楼,按“上”可以到44楼,按“下”是不起作用的,因为没有-2−2楼。那么,从AA楼到BB楼至少要按几次按钮呢?
输入输出格式
输入格式:
共二行。
第一行为33个用空格隔开的正整数,表示N,A,B(1≤N≤200, 1≤A,B≤N)N,A,B(1≤N≤200,1≤A,B≤N)。
第二行为NN个用空格隔开的非负整数,表示K_iKi。
输出格式:
一行,即最少按键次数,若无法到达,则输出-1−1。
输入样例
5 1 5
3 3 1 2 5
输出样例
3
思路:
暴力深搜+剪枝(注意回溯,取最少按键次数方案)
(代码附详细解释说明)
AC 代码:
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<map>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#define mod 998244353
#define Max 0x3f3f3f3f
#define Min 0xc0c0c0c0
#define mst(a) memset(a,0,sizeof(a))
#define f(i,a,b) for(int i=a;i<b;i++)
using namespace std;
typedef long long ll;
const int maxn=100005;
int n,a,b;
int ans=Max;
int arr[205];
bool vis[205]; //vis数组存储是否去过某楼层
void dfs(int sx,int sum){ //sx表示当前楼层,sum统计按键次数
if(sx==b){ //到达目的楼层
ans=min(ans,sum); //取最优方案
}
else if(sum<=ans){ //最优剪枝:当前按键次数sum>ans,必不可能为最优方案
vis[sx]=true; //标记去过的楼层
if(sx+arr[sx]<=n && vis[sx+arr[sx]]==false ){ //暴力深搜:上
dfs(sx+arr[sx],sum+1);
}
if(sx-arr[sx]>=1 && vis[sx-arr[sx]]==false){ //暴力深搜:下
dfs(sx-arr[sx],sum+1);
}
vis[sx]=false; //回溯
}
}
int main(){
ios::sync_with_stdio(false);
cin>>n>>a>>b;
for(int i=1;i<=n;i++){
cin>>arr[i];
}
memset(vis,false,sizeof(vis));
vis[a]=true; //记录来过初始楼层
dfs(a,0); //开始暴力深搜
if(ans!=Max){ //判断是否能到达目的楼层
cout<<ans<<endl;
}
else{
cout<<"-1"<<endl;
}
return 0;
}