1654. Minimum Jumps to Reach Home
问题:
一个虫子在x坐标的0位置出发,
求最少跳多少次能跳到x位置。
跳动规则:
- 不能跳到forbidden所示的位置
- 每次可向前跳 a 个距离。
- 每次可向后跳 b 个距离。不能连续向后跳两次。
- 不能跳到<0的坐标位置。
Example 1: Input: forbidden = [14,4,18,1,15], a = 3, b = 15, x = 9 Output: 3 Explanation: 3 jumps forward (0 -> 3 -> 6 -> 9) will get the bug home. Example 2: Input: forbidden = [8,3,16,6,12,20], a = 15, b = 13, x = 11 Output: -1 Example 3: Input: forbidden = [1,6,2,14,5,17,4], a = 16, b = 9, x = 7 Output: 2 Explanation: One jump forward (0 -> 16) then one jump backward (16 -> 7) will get the bug home. Constraints: 1 <= forbidden.length <= 1000 1 <= a, b, forbidden[i] <= 2000 0 <= x <= 2000 All the elements in forbidden are distinct. Position x is not forbidden.
解法:BFS
- 状态:
- 当前位置pos,最后一次跳动类型:向前?向后?
- visited,记录跳动到过的位置。
- 选择:(next位置>=0)
- 向前
- 向后:上一次不能是向后
⚠️ 注意:
- 本题没有限制跳动位置的上限,
- 因此为了防止TLE错误,我们需要判断跳动上限。maxbound
- 只有a<b的时候,才可以向回跳,也会出现先跳到超过x的位置,再往回跳的情况。
- 这时候上限为,可能到达的位置 max(x,forbidden),再往后尝试 最大 a+b
- 即: max(x,forbidden)+a+b。
- 当a>b的时候,只可能往前跳,此时pos如果超出x,且当前跳法是向后跳,那么之后的跳动只能使得离x越来越远。这种情况就不能再继续尝试了。
代码参考:
1 class Solution { 2 public: 3 int minimumJumps(vector<int>& forbidden, int a, int b, int x) { 4 //state: last try type:1:forward, 0:backward 5 // pos 6 //if try_type == forward(1): next can try both forward(1) and backward(0) 7 //if try_type == backward(0): next can try only forward(1) 8 //if a-b>0 && cur_try=backward && next-x>0: continue; 9 //if pos in forbidden continue; 10 //if pos in visited continue; 11 //if pos<0 || pos>2000 continue; 12 int tryt[2] = {-b, a}; 13 unordered_set<int> visited(forbidden.begin(), forbidden.end()); 14 queue<pair<int, int>> q; 15 q.push({0,0});//first try must be forward 16 visited.insert(0); 17 //get maxbound: only backward case(b>a) 18 //max pos we can reach=max(x,forbidden), + try_forwardmax(a+b) 19 int maxbound = x; 20 for(int fbd:forbidden) maxbound = max(maxbound, fbd); 21 maxbound = maxbound+a+b; 22 int step = 0; 23 while(!q.empty()) { 24 int sz = q.size(); 25 for(int i=0; i<sz; i++) { 26 auto [pos, trytype] = q.front(); 27 q.pop(); 28 if(pos==x) return step; 29 for(int j=0; j<2; j++) { 30 if(trytype==0 && j==0) continue; 31 int next = pos+tryt[j]; 32 if(a-b>0 && j==0 && next-x>0) continue; 33 if(next<0 || next>maxbound) continue; 34 if(visited.insert(next).second) { 35 q.push({next, j}); 36 } 37 } 38 } 39 step++; 40 } 41 return -1; 42 } 43 };