当前位置: 代码迷 >> 综合 >> 洛谷OJ - P1135 - 奇怪的电梯(DFS+回溯+减枝)
  详细解决方案

洛谷OJ - P1135 - 奇怪的电梯(DFS+回溯+减枝)

热度:20   发布时间:2023-10-09 14:33:14.0
题目描述

呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第i层楼(1<=i<=N)上有一个数字Ki(0<=Ki<=N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:3 3 1 2 5代表了Ki(K1=3,K2=3,……),从一楼开始。在一楼,按“上”可以到4楼,按“下”是不起作用的,因为没有-2楼。那么,从A楼到B楼至少要按几次按钮呢?

输入

输入文件共有二行,

第一行为三个用空格隔开的正整数,表示N,A,B(1≤N≤200, 1≤A,B≤N),

第二行为N个用空格隔开的正整数,表示Ki。

输出
输出文件仅一行,即最少按键次数,若无法到达,则输出-1。
样例输入
5 1 5
3 3 1 2 5
样例输出
3
题目思路

递归搜索时,最先搜到的结果并不一定是最优秀的,我们可以用一个变量来记录当前搜到的最小的结果来达到减枝的目的。其次我们可以利用回溯来加快程序的速度。

题目代码
#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <cstdio>
#include <vector>
#include <algorithm>
#define LL long long
#define INF 99999999
using namespace std;
int n, a, b;
int h[205];
int flag = 1;
int ans = INF;
int vis[201];
void dfs(int cur, int cnt){if(cnt > ans) // 减枝,记录当前最小次数 return; if(cur == b){flag = 0;ans = cnt;return ;}if(cur+h[cur] <= n){if(!vis[cur+h[cur]]){vis[cur+h[cur]] = 1;dfs(cur+h[cur], cnt+1);vis[cur+h[cur]] = 0;}}if(cur-h[cur] >= 1){if(!vis[cur-h[cur]]){vis[cur-h[cur]] = 1;dfs(cur-h[cur], cnt+1);vis[cur-h[cur]] = 0;}}return ;	
}int main(){scanf("%d%d%d",&n,&a,&b);memset(vis, 0, sizeof(vis));for(int i = 1; i <= n; i++){scanf("%d",&h[i]);}dfs(a,0);if(flag)puts("-1");elseprintf("%d\n",ans);return 0;
}