Minimum Jumps to Reach Home

medium bfs state space

Problem

A bug starts at position 0 on a number line and wants to reach its home at position x. Each jump moves it exactly a positions forward or b positions backward, but it may never jump backward twice in a row, never land on a negative position, and never land on any position listed in forbidden. Return the minimum number of jumps needed to land exactly on x, or −1 if home is unreachable.

Inputforbidden = [14,4,18,1,15], a = 3, b = 15, x = 9
Output3
Three forward jumps 0 → 3 → 6 → 9 land exactly on home; no backward jump is ever needed.

from collections import deque

def minimum_jumps(forbidden, a, b, x):
    limit = max([x] + forbidden) + a + b
    bad = set(forbidden)
    q = deque([(0, 0, 0)])          # position, back-flag, jumps
    seen = {(0, 0)}
    while q:
        pos, back, jumps = q.popleft()
        if pos == x:
            return jumps
        f = pos + a
        if f <= limit and f not in bad and (f, 0) not in seen:
            seen.add((f, 0))
            q.append((f, 0, jumps + 1))
        g = pos - b
        if not back and g >= 0 and g not in bad and (g, 1) not in seen:
            seen.add((g, 1))
            q.append((g, 1, jumps + 1))
    return -1
function minimumJumps(forbidden, a, b, x) {
  const limit = Math.max(x, ...forbidden, 0) + a + b;
  const bad = new Set(forbidden);
  const q = [[0, 0, 0]];            // position, back-flag, jumps
  const seen = new Set(["0,0"]);
  let head = 0;
  while (head < q.length) {
    const [pos, back, jumps] = q[head++];
    if (pos === x) return jumps;
    const f = pos + a;
    if (f <= limit && !bad.has(f) && !seen.has(f + ",0")) {
      seen.add(f + ",0");
      q.push([f, 0, jumps + 1]);
    }
    const g = pos - b;
    if (!back && g >= 0 && !bad.has(g) && !seen.has(g + ",1")) {
      seen.add(g + ",1");
      q.push([g, 1, jumps + 1]);
    }
  }
  return -1;
}
int minimumJumps(int[] forbidden, int a, int b, int x) {
    int limit = x;
    for (int f : forbidden) limit = Math.max(limit, f);
    limit += a + b;
    boolean[][] seen = new boolean[limit + 1][2];
    for (int f : forbidden) { seen[f][0] = true; seen[f][1] = true; }
    Deque<int[]> q = new ArrayDeque<>();
    q.add(new int[]{0, 0, 0});      // position, back-flag, jumps
    seen[0][0] = true;
    while (!q.isEmpty()) {
        int[] cur = q.poll();
        int pos = cur[0], back = cur[1], jumps = cur[2];
        if (pos == x) return jumps;
        int f = pos + a;
        if (f <= limit && !seen[f][0]) {
            seen[f][0] = true;
            q.add(new int[]{f, 0, jumps + 1});
        }
        int g = pos - b;
        if (back == 0 && g >= 0 && !seen[g][1]) {
            seen[g][1] = true;
            q.add(new int[]{g, 1, jumps + 1});
        }
    }
    return -1;
}
int minimumJumps(vector<int>& forbidden, int a, int b, int x) {
    int limit = x;
    for (int f : forbidden) limit = max(limit, f);
    limit += a + b;
    vector<array<bool, 2>> seen(limit + 1, {false, false});
    for (int f : forbidden) seen[f] = {true, true};
    queue<array<int, 3>> q;
    q.push({0, 0, 0});              // position, back-flag, jumps
    seen[0][0] = true;
    while (!q.empty()) {
        auto [pos, back, jumps] = q.front(); q.pop();
        if (pos == x) return jumps;
        int f = pos + a;
        if (f <= limit && !seen[f][0]) {
            seen[f][0] = true;
            q.push({f, 0, jumps + 1});
        }
        int g = pos - b;
        if (back == 0 && g >= 0 && !seen[g][1]) {
            seen[g][1] = true;
            q.push({g, 1, jumps + 1});
        }
    }
    return -1;
}
Time: O(max(x, maxF) + a + b) Space: O(max(x, maxF) + a + b)