Open In App

Snake and Ladder Problem

Last Updated : 26 Jun, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given a snake and ladder board, find the minimum number of dice throws required to reach the destination or last cell from the source or 1st cell. Basically, the player has total control over the outcome of the dice throw and wants to find out the minimum number of throws required to reach the last cell.
If the player reaches a cell which is the base of a ladder, the player has to climb up that ladder and if reaches a cell is the mouth of the snake, and has to go down to the tail of the snake without a dice throw.

Example:

Input:

Snake-and-Ladder-Problem

Output: 3
Explanation: Following are the steps:

  • First throw two dice to reach cell number 3 and then ladder to reach 22 
  • Then throw 6 to reach 28.
  • Finally through 2 to reach 30.
  • There can be other solutions as well like (2, 2, 6), (2, 4, 4), (2, 3, 5).. etc.

[Approach - 1] Using Breadth-First Search - O(n) Time and O(n) Space

The idea is to model the Snakes and Ladders board as a graph where each cell is a node and dice throws represent edges. The thought process is to use Breadth-First Search (BFS) since we're looking for the shortest path (minimum number of moves) from start to end. An important observation is that when you land on a cell with a ladder or snake, you're teleported to a new cell, this effectively changes the destination node of that edge. BFS explores all possible dice rolls from each cell in the shortest-first manner, ensuring we reach the final cell with the least number of throws.

Steps to implement the above idea:

  • Create a visited array to keep track of visited cells during the BFS traversal of the board.
  • Initialize a queue that stores pairs of current cell index and the number of moves taken.
  • Begin from cell 0 with distance 0, mark it visited, and push into the queue as the starting point.
  • While the queue is not empty, extract the front element and get its current cell and distance.
  • If the current cell is the last one, return the distance as it represents minimum dice throws.
  • Loop through all possible next 6 cells using a dice roll and for each, check snake or ladder jump.
  • If the destination cell is not visited, mark it visited and enqueue it with distance incremented by 1.
C++
// C++ program to find minimum number of dice throws
// in Snakes and Ladders using BFS
#include <iostream>
#include <vector>
#include <queue>
using namespace std;

// Function to find the minimum number of dice throws
int getMinDiceThrows(vector<int>& move) {
    int n = move.size();
    vector<bool> visited(n, false);
    queue<vector<int>> q;

    visited[0] = true;
    
    // Start from cell 0 with 0 moves
    q.push({0, 0}); 

    while (!q.empty()) {
        vector<int> curr = q.front();
        int v = curr[0];
        int dist = curr[1];

        if (v == n - 1)
            return dist; 

        q.pop();

        // Try all possible dice throws from current cell
        for (int j = v + 1; j <= v + 6 && j < n; ++j) {
            if (!visited[j]) {
                visited[j] = true;

                // Move to destination cell if 
                // there's a ladder/snake
                int dest = (move[j] != -1) ? move[j] : j;
                q.push({dest, dist + 1});
            }
        }
    }

    return -1;
}

int main() {
    int n = 30;
    vector<int> moves(n, -1);

    // Ladders
    moves[2] = 21;
    moves[4] = 7;
    moves[10] = 25;
    moves[19] = 28;

    // Snakes
    moves[26] = 0;
    moves[20] = 8;
    moves[16] = 3;
    moves[18] = 6;

    cout << getMinDiceThrows(moves);
    return 0;
}
Java
// Java program to find minimum number of dice throws
// in Snakes and Ladders using BFS
import java.util.*;

class GfG {

    // Function to find the minimum number of dice throws
    static int getMinDiceThrows(int[] move) {
        int n = move.length;
        boolean[] visited = new boolean[n];
        Queue<int[]> q = new LinkedList<>();

        visited[0] = true;

        // Start from cell 0 with 0 moves
        q.add(new int[]{0, 0});

        while (!q.isEmpty()) {
            int[] curr = q.peek();
            int v = curr[0];
            int dist = curr[1];

            if (v == n - 1)
                return dist;

            q.remove();

            // Try all possible dice throws from current cell
            for (int j = v + 1; j <= v + 6 && j < n; ++j) {
                if (!visited[j]) {
                    visited[j] = true;

                    // Move to destination cell if 
                    // there's a ladder/snake
                    int dest = (move[j] != -1) ? move[j] : j;
                    q.add(new int[]{dest, dist + 1});
                }
            }
        }

        return -1;
    }

    public static void main(String[] args) {
        int n = 30;
        int[] moves = new int[n];
        Arrays.fill(moves, -1);

        // Ladders
        moves[2] = 21;
        moves[4] = 7;
        moves[10] = 25;
        moves[19] = 28;

        // Snakes
        moves[26] = 0;
        moves[20] = 8;
        moves[16] = 3;
        moves[18] = 6;

        System.out.println(getMinDiceThrows(moves));
    }
}
Python
# Python program to find minimum number of dice throws
# in Snakes and Ladders using BFS
from collections import deque

# Function to find the minimum number of dice throws
def getMinDiceThrows(move):
    n = len(move)
    visited = [False] * n
    q = deque()

    visited[0] = True

    # Start from cell 0 with 0 moves
    q.append([0, 0])

    while q:
        curr = q[0]
        v = curr[0]
        dist = curr[1]

        if v == n - 1:
            return dist

        q.popleft()

        # Try all possible dice throws from current cell
        for j in range(v + 1, min(v + 7, n)):
            if not visited[j]:
                visited[j] = True

                # Move to destination cell if 
                # there's a ladder/snake
                dest = move[j] if move[j] != -1 else j
                q.append([dest, dist + 1])

    return -1

if __name__ == "__main__":
    n = 30
    moves = [-1] * n

    # Ladders
    moves[2] = 21
    moves[4] = 7
    moves[10] = 25
    moves[19] = 28

    # Snakes
    moves[26] = 0
    moves[20] = 8
    moves[16] = 3
    moves[18] = 6

    print(getMinDiceThrows(moves))
C#
// C# program to find minimum number of dice throws
// in Snakes and Ladders using BFS
using System;
using System.Collections.Generic;

class GfG {

    // Function to find the minimum number of dice throws
    public static int getMinDiceThrows(int[] move) {
        int n = move.Length;
        bool[] visited = new bool[n];
        Queue<int[]> q = new Queue<int[]>();

        visited[0] = true;

        // Start from cell 0 with 0 moves
        q.Enqueue(new int[] {0, 0});

        while (q.Count > 0) {
            int[] curr = q.Peek();
            int v = curr[0];
            int dist = curr[1];

            if (v == n - 1)
                return dist;

            q.Dequeue();

            // Try all possible dice throws from current cell
            for (int j = v + 1; j <= v + 6 && j < n; ++j) {
                if (!visited[j]) {
                    visited[j] = true;

                    // Move to destination cell if 
                    // there's a ladder/snake
                    int dest = (move[j] != -1) ? move[j] : j;
                    q.Enqueue(new int[] {dest, dist + 1});
                }
            }
        }

        return -1;
    }

    public static void Main() {
        int n = 30;
        int[] moves = new int[n];
        Array.Fill(moves, -1);

        // Ladders
        moves[2] = 21;
        moves[4] = 7;
        moves[10] = 25;
        moves[19] = 28;

        // Snakes
        moves[26] = 0;
        moves[20] = 8;
        moves[16] = 3;
        moves[18] = 6;

        Console.WriteLine(getMinDiceThrows(moves));
    }
}
JavaScript
// Javascript program to find minimum number of dice throws
// in Snakes and Ladders using BFS

// Function to find the minimum number of dice throws
function getMinDiceThrows(move) {
    let n = move.length;
    let visited = new Array(n).fill(false);
    let q = [];

    visited[0] = true;

    // Start from cell 0 with 0 moves
    q.push([0, 0]);

    while (q.length > 0) {
        let curr = q[0];
        let v = curr[0];
        let dist = curr[1];

        if (v === n - 1)
            return dist;

        q.shift();

        // Try all possible dice throws from current cell
        for (let j = v + 1; j <= v + 6 && j < n; ++j) {
            if (!visited[j]) {
                visited[j] = true;

                // Move to destination cell if 
                // there's a ladder/snake
                let dest = (move[j] !== -1) ? move[j] : j;
                q.push([dest, dist + 1]);
            }
        }
    }

    return -1;
}

// Driver Code
let n = 30;
let moves = new Array(n).fill(-1);

// Ladders
moves[2] = 21;
moves[4] = 7;
moves[10] = 25;
moves[19] = 28;

// Snakes
moves[26] = 0;
moves[20] = 8;
moves[16] = 3;
moves[18] = 6;

console.log(getMinDiceThrows(moves));

Output
3

[Approach - 2] Using Depth-First Search - O(n) Time and O(n) Space

The idea is to simulate all possible dice throws using Depth First Search (DFS) to explore every path from start to finish. The thought process is to move from the current position to all possible next positions (via dice throw 1–6), jumping to a new location if there's a snake or ladder. An important observation is to prune paths that are already worse than a previously found one using a visited map that tracks minimum moves at each cell. This ensures we only pursue optimal paths, and stop early when a shorter one is already found.

Steps to implement the above idea:

  • Define a recursive function that explores all possible paths from the current position with a move counter.
  • Use a map to track visited positions and the least number of moves needed to reach each of them.
  • Add a base case to update the minimum moves if the current path reaches the final destination.
  • Prune the recursion if the current path takes more moves than already recorded for the same position.
  • For each call, simulate all dice throws from 1 to 6 and compute the next position accordingly.
  • If the next cell has a ladder or snake, jump to its destination before making the recursive call.
  • Start the function from position 0, and return -1 if no valid path reaches the end of the board.
C++
// C++ program to find minimum number of dice throws
// in Snakes and Ladders using DFS 
#include <iostream>
#include <vector>
#include <climits>
#include <unordered_map>
using namespace std;

// Recursive DFS to explore all paths from current position
void dfs(int currPos, int movesMade, vector<int>& move,
         unordered_map<int, int>& visited, int n, int& res) {

    // Prune paths that are worse than already found or visited
    if (movesMade >= res || 
        (visited.count(currPos) && movesMade >= visited[currPos])) {
        return;
    }

    // Reached the last cell, update result
    if (currPos == n - 1) {
        res = movesMade;
        return;
    }

    visited[currPos] = movesMade;

    // Explore all dice throws (1 to 6)
    for (int i = 1; i <= 6 && currPos + i < n; ++i) {
        int nextPos = currPos + i;

        // Jump if ladder/snake present
        int dest = (move[nextPos] != -1) ? move[nextPos] : nextPos;

        dfs(dest, movesMade + 1, move, visited, n, res);
    }
}

// Function to find the minimum number of dice throws
int getMinDiceThrows(vector<int>& move) {
    int n = move.size();
    unordered_map<int, int> visited;
    int res = INT_MAX;

    // Start DFS from cell 0
    dfs(0, 0, move, visited, n, res);

    return (res == INT_MAX) ? -1 : res;
}

int main() {
    int n = 30;
    vector<int> moves(n, -1);

    // Ladders
    moves[2] = 21;
    moves[4] = 7;
    moves[10] = 25;
    moves[19] = 28;

    // Snakes
    moves[26] = 0;
    moves[20] = 8;
    moves[16] = 3;
    moves[18] = 6;

    cout << getMinDiceThrows(moves);
    return 0;
}
Java
// Java program to find minimum number of dice throws
// in Snakes and Ladders using DFS 
import java.util.*;

class GfG {

    // Recursive DFS to explore all paths from current position
    static void dfs(int currPos, int movesMade, int[] move,
                    Map<Integer, Integer> visited, int n, int[] res) {

        // Prune paths that are worse than already found or visited
        if (movesMade >= res[0] || 
            (visited.containsKey(currPos) && movesMade >= visited.get(currPos))) {
            return;
        }

        // Reached the last cell, update result
        if (currPos == n - 1) {
            res[0] = movesMade;
            return;
        }

        visited.put(currPos, movesMade);

        // Explore all dice throws (1 to 6)
        for (int i = 1; i <= 6 && currPos + i < n; ++i) {
            int nextPos = currPos + i;

            // Jump if ladder/snake present
            int dest = (move[nextPos] != -1) ? move[nextPos] : nextPos;

            dfs(dest, movesMade + 1, move, visited, n, res);
        }
    }

    // Function to find the minimum number of dice throws
    static int getMinDiceThrows(int[] move) {
        int n = move.length;
        Map<Integer, Integer> visited = new HashMap<>();
        int[] res = {Integer.MAX_VALUE};

        // Start DFS from cell 0
        dfs(0, 0, move, visited, n, res);

        return (res[0] == Integer.MAX_VALUE) ? -1 : res[0];
    }

    public static void main(String[] args) {
        int n = 30;
        int[] moves = new int[n];
        Arrays.fill(moves, -1);

        // Ladders
        moves[2] = 21;
        moves[4] = 7;
        moves[10] = 25;
        moves[19] = 28;

        // Snakes
        moves[26] = 0;
        moves[20] = 8;
        moves[16] = 3;
        moves[18] = 6;

        System.out.println(getMinDiceThrows(moves));
    }
}
Python
# Python program to find minimum number of dice throws
# in Snakes and Ladders using DFS 
import sys

# Recursive DFS to explore all paths from current position
def dfs(currPos, movesMade, move, visited, n, res):
    
    # Prune paths that are worse than already found or visited
    if movesMade >= res[0] or (currPos in visited and movesMade >= visited[currPos]):
        return

    # Reached the last cell, update result
    if currPos == n - 1:
        res[0] = movesMade
        return

    visited[currPos] = movesMade

    # Explore all dice throws (1 to 6)
    for i in range(1, 7):
        if currPos + i < n:
            nextPos = currPos + i

            # Jump if ladder/snake present
            dest = move[nextPos] if move[nextPos] != -1 else nextPos

            dfs(dest, movesMade + 1, move, visited, n, res)

# Function to find the minimum number of dice throws
def getMinDiceThrows(move):
    n = len(move)
    visited = {}
    res = [sys.maxsize]

    # Start DFS from cell 0
    dfs(0, 0, move, visited, n, res)

    return -1 if res[0] == sys.maxsize else res[0]

if __name__ == "__main__":
    n = 30
    moves = [-1] * n

    # Ladders
    moves[2] = 21
    moves[4] = 7
    moves[10] = 25
    moves[19] = 28

    # Snakes
    moves[26] = 0
    moves[20] = 8
    moves[16] = 3
    moves[18] = 6

    print(getMinDiceThrows(moves))
C#
// C# program to find minimum number of dice throws
// in Snakes and Ladders using DFS 
using System;
using System.Collections.Generic;

class GfG {

    // Recursive DFS to explore all paths from current position
    static void dfs(int currPos, int movesMade, int[] move,
                    Dictionary<int, int> visited, int n, ref int res) {

        // Prune paths that are worse than already found or visited
        if (movesMade >= res || 
            (visited.ContainsKey(currPos) && movesMade >= visited[currPos])) {
            return;
        }

        // Reached the last cell, update result
        if (currPos == n - 1) {
            res = movesMade;
            return;
        }

        visited[currPos] = movesMade;

        // Explore all dice throws (1 to 6)
        for (int i = 1; i <= 6 && currPos + i < n; ++i) {
            int nextPos = currPos + i;

            // Jump if ladder/snake present
            int dest = (move[nextPos] != -1) ? move[nextPos] : nextPos;

            dfs(dest, movesMade + 1, move, visited, n, ref res);
        }
    }

    // Function to find the minimum number of dice throws
    static int getMinDiceThrows(int[] move) {
        int n = move.Length;
        var visited = new Dictionary<int, int>();
        int res = int.MaxValue;

        // Start DFS from cell 0
        dfs(0, 0, move, visited, n, ref res);

        return (res == int.MaxValue) ? -1 : res;
    }

    static void Main() {
        int n = 30;
        int[] moves = new int[n];
        Array.Fill(moves, -1);

        // Ladders
        moves[2] = 21;
        moves[4] = 7;
        moves[10] = 25;
        moves[19] = 28;

        // Snakes
        moves[26] = 0;
        moves[20] = 8;
        moves[16] = 3;
        moves[18] = 6;

        Console.WriteLine(getMinDiceThrows(moves));
    }
}
JavaScript
// JavaScript program to find minimum number of dice throws
// in Snakes and Ladders using DFS 

// Recursive DFS to explore all paths from current position
function dfs(currPos, movesMade, move, visited, n, res) {

    // Prune paths that are worse than already found or visited
    if (movesMade >= res[0] || 
        (visited.has(currPos) && movesMade >= visited.get(currPos))) {
        return;
    }

    // Reached the last cell, update result
    if (currPos === n - 1) {
        res[0] = movesMade;
        return;
    }

    visited.set(currPos, movesMade);

    // Explore all dice throws (1 to 6)
    for (let i = 1; i <= 6 && currPos + i < n; ++i) {
        let nextPos = currPos + i;

        // Jump if ladder/snake present
        let dest = (move[nextPos] !== -1) ? move[nextPos] : nextPos;

        dfs(dest, movesMade + 1, move, visited, n, res);
    }
}

// Function to find the minimum number of dice throws
function getMinDiceThrows(move) {
    let n = move.length;
    let visited = new Map();
    let res = [Number.MAX_SAFE_INTEGER];

    // Start DFS from cell 0
    dfs(0, 0, move, visited, n, res);

    return (res[0] === Number.MAX_SAFE_INTEGER) ? -1 : res[0];
}

// Driver Code
let n = 30;
let moves = new Array(n).fill(-1);

// Ladders
moves[2] = 21;
moves[4] = 7;
moves[10] = 25;
moves[19] = 28;

// Snakes
moves[26] = 0;
moves[20] = 8;
moves[16] = 3;
moves[18] = 6;

console.log(getMinDiceThrows(moves));

Output
3


 


Next Article

Similar Reads