Minimum Jumps to Reach Home

A certain bug's home is on the x-axis at position x. Help them get there from position 0.

The bug jumps according to the following rules:

The bug may jump forward beyond its home, but it cannot jump to positions numbered with negative integers.

Given an array of integers forbidden, where forbidden[i] means that the bug cannot jump to the position forbidden[i], and integers a, b, and x, return the minimum number of jumps needed for the bug to reach its home. If there is no possible sequence of jumps that lands the bug on position x, return -1.

 

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:


Solution:

proof of maxLimit:

https://leetcode-cn.com/problems/minimum-jumps-to-reach-home/solution/dao-jia-de-zui-shao-tiao-yue-ci-shu-zui-duan-lu-zh/

class Solution {
    public int minimumJumps(int[] forbidden, int a, int b, int x) {
        Set<Integer> noGo = new HashSet();
        /*
        M + a + x is sufficient, where M is the maximal values of forbidden or x. Consider the scenario to jump forward m times and backward n times to reach x, that is m * a - n * b = x. We can equivalently jump backward as earlier as possible. That is, jump backward whenever position p > M, p - b is not forbidden and there is still backward jump remains. Such p could be as large as M + a + b.
        */
        int maxLimit = x + a + b;
        for (int val : forbidden) {
            maxLimit = Math.max(maxLimit, val + a + b);
            noGo.add(val);
        }
        Set<List<Integer>> visited = new HashSet();
        visited.add(Arrays.asList(0, 0));
        Deque<List<Integer>> queue = new ArrayDeque();
        queue.offer(Arrays.asList(0, 0));
        int step = 0;
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i ++) {
                List<Integer> curr = queue.poll();
                if (curr.get(0) == x) return step;
                List<Integer> forward = Arrays.asList(curr.get(0) + a, 0);
                if (!noGo.contains(forward.get(0)) && (forward.get(0) <= maxLimit) && visited.add(forward)) {
                    queue.offer(forward);
                }
                if (curr.get(1) == 0) {
                    List<Integer> backward = Arrays.asList(curr.get(0) - b, 1);
                    if (backward.get(0) > 0 && !noGo.contains(backward.get(0)) && visited.add(backward)) {
                        queue.offer(backward);
                    }
                }
            }
            step ++;
        }
        return -1;
    }
}