这道题其实用bfs会更加方便,这里的题目前面的测试点是卡的dfs的点,所以如果你用的dfs进行暴搜的话,前面的几个测试点就会TLE,因此需要用比较高效的bfs。这里就不讲bfs了,等到后面做到bfs的点之后再回过头来看,这里只讲dfs的比较暴力的解法。
思路:其实思路很简单,我们从题目中可以知道,这是一个指数型的递归,对于我们所在的每一层来说,都有选择上层或者下层的选择,就这两种选择,所以我们就需要两次dfs的递归。
如果我们不剪枝的情况下,大多数就会变成MLE的情况。为什么呢?我们考虑一种可能性:
假设我们现在在1层,需要上5层,这时我们的过程可能是1-2-...-2-5,也可能是1-2-...-5。那么问题来了,这个时候我们需要选择哪一种方案呢?答案很明显,我们需要选择第二种方案才能保证最佳,而且,在我们递归的时候也不排除有无限循环的时候,就比如刚刚那个2-2-2等等,这都会造成你的内存消耗太多,并且也会让时间超时,因此避免这种情况的发生,我们有一个状态数组来标记我们来过的楼层,这样才能保证我们不会在后面选择楼层的时候出现同一个楼层的情况。
在我们进行判断标记的时候,不要忘记标记当前我们dfs遍历的地方,然后再去判断我们将要去的楼层是否该不该去。这样剪枝差不多就行了,如果你不放心,那就在前面加上判断操作次数和判断位置的剪枝就行,这样除去那几个卡DFS得测试点以外,我们就都能通过。
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<algorithm>
#include<stack>
#include<queue>
#include<sstream>
#include<map>
#include<limits.h>
#include<set>
#define MAX 205
#define _for(i,a,b) for(int i=a;i<(b);i++)
#define ALL(x) x.begin(),x.end()
using namespace std;
typedef long long LL;
LL n, m, counts=0;
LL A, B;
int res = 1e9;
LL arr[MAX];
int st[MAX];
bool flag = false;
void dfs(int u,int op) {
if (op >= res)
return;
if (u == B) {
res = min(res, op);
return;
}
st[u] = true;
if (u + arr[u] <= n && !st[u + arr[u]]) {
st[u + arr[u]] = 1;
dfs(u + arr[u], op + 1);
st[u + arr[u]] = 0;
}
if (u - arr[u] > 0 && !st[u - arr[u]]) {
st[u - arr[u]] = 1;
dfs(u - arr[u], op + 1);
st[u - arr[u]] = 0;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
cin >> n;
cin >> A >> B;
_for(i, 1, n + 1)
cin >> arr[i];
dfs(A,0);
if (res == 1e9)
cout << -1 << endl;
else
cout << res << endl;
return 0;
}