题目描述
有一只跳蚤的家在数轴上的位置 x 处。请你帮助它从位置 0 出发,到达它的家。
跳蚤跳跃的规则如下:
- 它可以 往前 跳恰好 a 个位置(即往右跳)。
- 它可以 往后 跳恰好 b 个位置(即往左跳)。
- 它不能 连续 往后跳 2 次。
- 它不能跳到任何 forbidden 数组中的位置。
- 跳蚤可以往前跳 超过 它的家的位置,但是它 不能跳到负整数 的位置。
给你一个整数数组 forbidden ,其中 forbidden[i] 是跳蚤不能跳到的位置,同时给你整数 a, b 和 x ,请你返回跳蚤到家的最少跳跃次数。如果没有恰好到达 x 的可行方案,请你返回 -1
思路一:BFS
- 使用BFS搜索所有可能路径
- 使用
struct pos
保存跳蚤所在点的坐标,已走步数,以及是否是通过后退到达此地 - 使用
struct vis
保存经过的点以及经过该点时的行进方向 - 因为搜索无界,所以处理无解情况时,要求解搜索上限
- 个人认为第三种情况
a<b
真的很难理解,也是死磕最久的部分,但是也可以取巧,因为题给的数据范围是
1 < = f o r b i d d e n . l e n g t h < = 1000 1 <= forbidden.length <= 1000 1<=forbidden.length<=1000
1 < = a , b , f o r b i d d e n [ i ] < = 2000 1 <= a, b, forbidden[i] <= 2000 1<=a,b,forbidden[i]<=2000
0 < = x < = 2000 0 <= x <= 2000 0<=x<=2000 - 所以可以将搜索上限定为6000
- 当
a=b
,一直向前行走即可,当超过x后仍然没有到则停止搜索,则上限为x
- 当
a>b
,当超出x,再向后退一次时仍大于x,则停止搜索,则上限为x+b
- 当
a<b
,上限为max(max(forbidden)+a+b,x)
,
- 个人认为第三种情况
class Solution {
public:
typedef struct pos{
int val=0;
int steps=0;
int back_cnt=0;
}pos;
typedef struct Visit{
int forward=0;
int backward=0;
}vis;
int minimumJumps(vector<int>& forbidden, int a, int b, int x) {
unordered_set<int>ban;
map<int,vis>visited;
queue<pos>q;
pos p;
for(int i=0;i<forbidden.size();i++){
ban.insert(forbidden[i]);
}
q.push(p);
int cnt=0;
while(!q.empty()){
cnt++;
p=q.front();
q.pop();
if(p.val==x){
return p.steps;
}
pos p1=p,p2=p;
if(p.val-b>=0&&ban.find(p.val-b)==ban.end()&&p.back_cnt==0){
p2.val-=b;
p2.steps++;
p2.back_cnt=1;
if(visited.find(p.val)==visited.end()){
vis v;
v.backward=1;
visited[p.val]=v;
q.push(p2);
}else{
if(visited[p.val].backward==0){
visited[p.val].backward=1;
q.push(p2);
}
}
}
if(ban.find(p.val+a)==ban.end()&&p.val+a<=6000){
p1.val+=a;
p1.steps++;
p1.back_cnt=0;
if(visited.find(p.val)==visited.end()){
vis v;
v.forward=1;
visited[p.val]=v;
q.push(p1);
}else{
if(visited[p.val].forward==0){
visited[p.val].forward=1;
q.push(p1);
}
}
}
}
return -1;
}
};