Minimize steps for Knight to collect maximum points (Knight in Geekland) (original) (raw)

In **Geekland, a knight is positioned at coordinates ****(start_x, start_y)** within an **N x M matrix. Each cell in the matrix contains a certain number of points. The knight has a unique ability to collect all the points from cells that can be reached in exactly **i steps without revisiting any cell. Additionally, the knight possesses magical powers, allowing it to fetch points from future steps. If the knight can collect y points in the xth step, it can also fetch all the points it will collect in the (x + y)th step, and so on.

For instance, if the knight can collect **1 point in the **1st step, it will also collect all points at the 2nd step (1+1), and if it can collect **3 points in the (1+1)th step, it will also fetch all points at the (1+1+3)th step. Therefore, even at the 1st step, the knight can collect an overall total of **1+3=4 points if there are no points available at the (1+1+3)th step.

The task is to determine the **minimum number of steps required for the knight to collect the **maximum possible points. The knight moves exactly like a chessboard knight, following 0 indexing.

**Note: The knight can move in an L-shaped pattern, similar to a knight's movement in chess.

**Example:

**Input: n = 9, m = 10, start_x = 4, start_y = 5,
arr = {
{0, 0, 0, 2, 0, 2, 0, 2, 0, 0},
{0, 0, 2, 0, 2, 0, 2, 0, 2, 0},
{0, 2, 0, 0, 1, 2, 0, 0, 0, 2},
{0, 0, 2, 0, 2, 0, 2, 0, 2, 0},
{0, 2, 0, 2, 0, 0, 0, 2, 0, 2},
{0, 0, 2, 0, 2, 0, 2, 0, 2, 0},
{0, 2, 0, 0, 0, 2, 0, 0, 0, 2},
{0, 0, 2, 0, 2, 0, 2, 0, 2, 0},
{0, 0, 0, 2, 0, 2, 0, 2, 0, 0} };
**Output: 1

**Input: int n2 = 3, m2 = 3, start_x2 = 2, start_y2 = 1;
arr =
{7, 6, 8},
{9, 1, 4},
{6, 2, 8} };
**Output: 0

**Approach:

The idea is to use a Breadth-First Search (BFS) Algorithm to explore the grid. It maintains a queue of cells to visit, starting with the knight’s initial position. For each cell, it calculates the points that can be collected from that cell and updates the total points.

The BFS algorithm will continues until all cells have been visited. The points from each cell are added to the total points, and if the points from a cell plus its index is less than the size of the grid, the points are added again.

Finally, iterates over the points collected at each step and returns the index of the step that collected the maximum points..

Steps-by-step approach:

Below is the implementation of the above approach:

C++ `

#include #include #include

using namespace std;

// Function to find the maximum score starting from the // given position int knightInGeekland(int start_x, int start_y, vector<vector >& arr) { int n = arr.size(); // number of rows int m = arr[0].size(); // number of columns

vector<vector<int> > vis(
    n,
    vector<int>(m)); // create a visited matrix to keep
                     // track of visited positions
vis[start_x][start_y]
    = 1; // mark the starting position as visited
queue<pair<int, int> >
    q; // create a queue to perform breadth-first search
q.push({ start_x, start_y }); // push the starting
                              // position into the queue

vector<int> list; // create a list to store the score
                  // obtained at each level
int points = 0; // initialize the points to 0

int dx[8] = {
    -2, -1, 1, 2, 2, 1, -1, -2
}; // array to store possible x-direction moves
int dy[8] = {
    1, 2, 2, 1, -1, -2, -2, -1
}; // array to store possible y-direction moves

// Helper function to check if the given position is
// safe or not
auto isSafe = [&](int i, int j) {
    return (i >= 0 and j >= 0 and i < n
            and j < m); // returns true if the position
                        // is within the matrix bounds
};

while (q.size()) { // while the queue is not empty

    int size
        = q.size(); // get the current size of the queue

    points = 0; // reset the points for each level

    for (int i = 0; i < size;
         i++) { // process all the elements in the
                // current level
        auto tmp = q.front(); // get the front element
        q.pop(); // remove the front element from the
                 // queue
        int x = tmp.first,
            y
            = tmp.second; // get the x and y coordinates

        points
            += arr[x]
                  [y]; // add the score at the current
                       // position to the points

        // check all possible moves from the current
        // position
        for (int k = 0; k < 8; k++) {
            int xi
                = x + dx[k]; // get the new x coordinate
            int xj
                = y + dy[k]; // get the new y coordinate

            // if the new position is safe and not
            // visited, mark it as visited and push it
            // into the queue
            if (isSafe(xi, xj) && !vis[xi][xj]) {
                vis[xi][xj] = 1; // mark the new
                                 // position as visited
                q.push({ xi,
                         xj }); // push the new position
                                // into the queue
            }
        }
    }
    list.push_back(
        points); // add the points obtained at the
                 // current level to the list
}

int max = -1,
    ans = -1; // variables to store the maximum score
              // and the answer position

// iterate backward through the list
for (int i = list.size() - 1; i >= 0; i--) {

    // if the next position is within the list bounds,
    // add it to the current score
    if (list[i] + i < list.size())
        list[i] += list[i + list[i]];
}

// find the maximum score and its position
for (int i = 0; i < list.size(); i++) {
    if (list[i] > max) {
        max = list[i]; // update the maximum score
        ans = i; // update the answer position
    }
}
return ans; // return the answer position

}

int main() { // Provided input int n = 9, m = 10; int start_x = 4, start_y = 5; vector<vector > arr = { { 0, 0, 0, 2, 0, 2, 0, 2, 0, 0 }, { 0, 0, 2, 0, 2, 0, 2, 0, 2, 0 }, { 0, 2, 0, 0, 1, 2, 0, 0, 0, 2 }, { 0, 0, 2, 0, 2, 0, 2, 0, 2, 0 }, { 0, 2, 0, 2, 0, 0, 0, 2, 0, 2 }, { 0, 0, 2, 0, 2, 0, 2, 0, 2, 0 }, { 0, 2, 0, 0, 0, 2, 0, 0, 0, 2 }, { 0, 0, 2, 0, 2, 0, 2, 0, 2, 0 }, { 0, 0, 0, 2, 0, 2, 0, 2, 0, 0 } };

// Call the knightInGeekland function with the provided
// input
int result = knightInGeekland(start_x, start_y, arr);

// Output the result
cout << "The maximum score starting from the given "
        "position is: "
     << result << endl;

return 0;

}

Java

import java.util.*; import java.util.function.Predicate;

public class KnightInGeekland {

// Function to find the maximum score starting from the
// given position
public static int
knightInGeekland(int start_x, int start_y, int[][] arr)
{
    int n = arr.length; // number of rows
    int m = arr[0].length; // number of columns

    int[][] vis
        = new int[n]
                 [m]; // create a visited matrix to keep
                      // track of visited positions
    vis[start_x][start_y]
        = 1; // mark the starting position as visited
    Queue<int[]> q
        = new LinkedList<>(); // create a queue to
                              // perform breadth-first
                              // search
    q.add(new int[] {
        start_x, start_y }); // push the starting
                             // position into the queue

    List<Integer> list
        = new ArrayList<>(); // create a list to store
                             // the score obtained at
                             // each level
    int points = 0; // initialize the points to 0

    int[] dx = {
        -2, -1, 1, 2, 2, 1, -1, -2
    }; // array to store possible x-direction moves
    int[] dy = {
        1, 2, 2, 1, -1, -2, -2, -1
    }; // array to store possible y-direction moves

    // Helper function to check if the given position is
    // safe or not
    Predicate<int[]> isSafe = (pos)
        -> pos[0] >= 0 && pos[1] >= 0 && pos[0] < n
               && pos[1] < m;

    while (
        !q.isEmpty()) { // while the queue is not empty

        int size = q.size(); // get the current size of
                             // the queue
        points = 0; // reset the points for each level

        for (int i = 0; i < size;
             i++) { // process all the elements in the
                    // current level
            int[] tmp
                = q.poll(); // get the front element
            int x = tmp[0],
                y
                = tmp[1]; // get the x and y coordinates

            points += arr[x][y]; // add the score at the
                                 // current position to
                                 // the points

            // check all possible moves from the current
            // position
            for (int k = 0; k < 8; k++) {
                int xi = x + dx[k]; // get the new x
                                    // coordinate
                int xj = y + dy[k]; // get the new y
                                    // coordinate

                // if the new position is safe and not
                // visited, mark it as visited and push
                // it into the queue
                if (isSafe.test(new int[] { xi, xj })
                    && vis[xi][xj] == 0) {
                    vis[xi][xj]
                        = 1; // mark the new position as
                             // visited
                    q.add(new int[] {
                        xi,
                        xj }); // push the new position
                               // into the queue
                }
            }
        }
        list.add(
            points); // add the points obtained at the
                     // current level to the list
    }

    int max = -1,
        ans = -1; // variables to store the maximum
                  // score and the answer position

    // iterate backward through the list
    for (int i = list.size() - 1; i >= 0; i--) {
        if (list.get(i) + i < list.size()) {
            list.set(i,
                     list.get(i)
                         + list.get(i + list.get(i)));
        }
    }

    // find the maximum score and its position
    for (int i = 0; i < list.size(); i++) {
        if (list.get(i) > max) {
            max = list.get(
                i); // update the maximum score
            ans = i; // update the answer position
        }
    }
    return ans; // return the answer position
}

public static void main(String[] args)
{
    // Provided input
    int n = 9, m = 10;
    int start_x = 4, start_y = 5;
    int[][] arr = { { 0, 0, 0, 2, 0, 2, 0, 2, 0, 0 },
                    { 0, 0, 2, 0, 2, 0, 2, 0, 2, 0 },
                    { 0, 2, 0, 0, 1, 2, 0, 0, 0, 2 },
                    { 0, 0, 2, 0, 2, 0, 2, 0, 2, 0 },
                    { 0, 2, 0, 2, 0, 0, 0, 2, 0, 2 },
                    { 0, 0, 2, 0, 2, 0, 2, 0, 2, 0 },
                    { 0, 2, 0, 0, 0, 2, 0, 0, 0, 2 },
                    { 0, 0, 2, 0, 2, 0, 2, 0, 2, 0 },
                    { 0, 0, 0, 2, 0, 2, 0, 2, 0, 0 } };

    // Call the knightInGeekland function with the
    // provided input
    int result
        = knightInGeekland(start_x, start_y, arr);

    // Output the result
    System.out.println(
        "The maximum score starting from the given position is: "
        + result);
}

}

Python3

Python program for the above approach

from collections import deque

Function to find the maximum score starting from the given position

def knight_in_geekland(start_x, start_y, arr): n = len(arr) # number of rows m = len(arr[0]) # number of columns

vis = [[0] * m for _ in range(n)]  # create a visited matrix to keep track of visited positions
vis[start_x][start_y] = 1  # mark the starting position as visited

q = deque([(start_x, start_y)])  # create a queue to perform breadth-first search
list_points = []  # create a list to store the score obtained at each level
points = 0  # initialize the points to 0

dx = [-2, -1, 1, 2, 2, 1, -1, -2]  # array to store possible x-direction moves
dy = [1, 2, 2, 1, -1, -2, -2, -1]  # array to store possible y-direction moves

# Helper function to check if the given position is safe or not
def is_safe(i, j):
    return 0 <= i and i < n and 0 <= j and j < m  # returns true if the position is within the matrix bounds

while q:  # while the queue is not empty
    size = len(q)  # get the current size of the queue
    points = 0  # reset the points for each level

    for _ in range(size):  # process all the elements in the current level
        x, y = q.popleft()  # get the front element
        points += arr[x][y]  # add the score at the current position to the points

        # check all possible moves from the current position
        for k in range(8):
            xi, xj = x + dx[k], y + dy[k]  # get the new x and y coordinates

            # if the new position is safe and not visited, mark it as visited and push it into the queue
            if is_safe(xi, xj) and not vis[xi][xj]:
                vis[xi][xj] = 1  # mark the new position as visited
                q.append((xi, xj))  # push the new position into the queue

    list_points.append(points)  # add the points obtained at the current level to the list

mx = -1
ans = -1  # variable to store the answer position

# iterate backward through the list
for i in range(len(list_points) - 1, -1, -1):
    # if the next position is within the list bounds,
    # add it to the current score
    if list_points[i] + i < len(list_points):
        list_points[i] += list_points[i + list_points[i]]

# find the maximum score and its position
for i in range(len(list_points)):
    if list_points[i] > mx:
          mx = list_points[i] # update the maximum score
          ans = i  # update the answer position
        
return ans  # return the answer position

Provided input

n, m = 9, 10 start_x, start_y = 4, 5 arr = [ [0, 0, 0, 2, 0, 2, 0, 2, 0, 0], [0, 0, 2, 0, 2, 0, 2, 0, 2, 0], [0, 2, 0, 0, 1, 2, 0, 0, 0, 2], [0, 0, 2, 0, 2, 0, 2, 0, 2, 0], [0, 2, 0, 2, 0, 0, 0, 2, 0, 2], [0, 0, 2, 0, 2, 0, 2, 0, 2, 0], [0, 2, 0, 0, 0, 2, 0, 0, 0, 2], [0, 0, 2, 0, 2, 0, 2, 0, 2, 0], [0, 0, 0, 2, 0, 2, 0, 2, 0, 0] ]

Call the knight_in_geekland function with the provided input

result = knight_in_geekland(start_x, start_y, arr)

Output the result

print("The maximum score starting from the given position is:", result)

This code is contributed by Susobhan Akhuli

C#

// C# program for the above approach using System; using System.Collections.Generic;

public class GFG { // Function to find the maximum score starting from the // given position static int KnightInGeekland(int start_x, int start_y, List<List > arr) { int n = arr.Count; // number of rows int m = arr[0].Count; // number of columns

    List<List<int> > vis = new List<List<int> >(n);
    for (int i = 0; i < n; i++) {
        vis.Add(new List<int>(m));
        for (int j = 0; j < m; j++) {
            vis[i].Add(
                0); // create a visited matrix to keep
                    // track of visited positions
        }
    }

    vis[start_x][start_y]
        = 1; // mark the starting position as visited
    Queue<Tuple<int, int> > q = new Queue<Tuple<
        int, int> >(); // create a queue to perform
                       // breadth-first search
    q.Enqueue(new Tuple<int, int>(
        start_x,
        start_y)); // enqueue the starting position

    List<int> list
        = new List<int>(); // create a list to store the
                           // score obtained at each
                           // level
    int points = 0; // initialize the points to 0

    int[] dx = {
        -2, -1, 1, 2, 2, 1, -1, -2
    }; // array to store possible x-direction moves
    int[] dy = {
        1, 2, 2, 1, -1, -2, -2, -1
    }; // array to store possible y-direction moves

    // Helper function to check if the given position is
    // safe or not
    Func<int, int, bool> isSafe = (i, j) => i >= 0 && j >= 0 && i < n && j < m;

    while (q.Count > 0) // while the queue is not empty
    {
        int size = q.Count; // get the current size of
                            // the queue
        points = 0; // reset the points for each level

        for (int i = 0; i < size;
             i++) // process all the elements in the
                  // current level
        {
            Tuple<int, int> tmp
                = q.Dequeue(); // get the front element
            int x = tmp.Item1,
                y = tmp.Item2; // get the x and y
                               // coordinates

            points += arr[x][y]; // add the score at the
                                 // current position to
                                 // the points

            // check all possible moves from the current
            // position
            for (int k = 0; k < 8; k++) {
                int xi = x + dx[k]; // get the new x
                                    // coordinate
                int xj = y + dy[k]; // get the new y
                                    // coordinate

                // if the new position is safe and not
                // visited, mark it as visited and
                // enqueue it
                if (isSafe(xi, xj)
                    && vis[xi][xj] == 0) {
                    vis[xi][xj]
                        = 1; // mark the new position as
                             // visited
                    q.Enqueue(new Tuple<int, int>(
                        xi, xj)); // enqueue the new
                                  // position
                }
            }
        }
        list.Add(
            points); // add the points obtained at the
                     // current level to the list
    }

    int max = -1,
        ans = -1; // variables to store the maximum
                  // score and the answer position

    // iterate backward through the list
    for (int i = list.Count - 1; i >= 0; i--) {
        // if the next position is within the list
        // bounds, add it to the current score
        if (list[i] + i < list.Count)
            list[i] += list[i + list[i]];
    }

    // find the maximum score and its position
    for (int i = 0; i < list.Count; i++) {
        if (list[i] > max) {
            max = list[i]; // update the maximum score
            ans = i; // update the answer position
        }
    }
    return ans; // return the answer position
}

static void Main()
{
    // Provided input
    // int n = 9, m = 10;
    int start_x = 4, start_y = 5;
    List<List<int> > arr = new List<List<int> >{
        new List<int>{ 0, 0, 0, 2, 0, 2, 0, 2, 0, 0 },
        new List<int>{ 0, 0, 2, 0, 2, 0, 2, 0, 2, 0 },
        new List<int>{ 0, 2, 0, 0, 1, 2, 0, 0, 0, 2 },
        new List<int>{ 0, 0, 2, 0, 2, 0, 2, 0, 2, 0 },
        new List<int>{ 0, 2, 0, 2, 0, 0, 0, 2, 0, 2 },
        new List<int>{ 0, 0, 2, 0, 2, 0, 2, 0, 2, 0 },
        new List<int>{ 0, 2, 0, 0, 0, 2, 0, 0, 0, 2 },
        new List<int>{ 0, 0, 2, 0, 2, 0, 2, 0, 2, 0 },
        new List<int>{ 0, 0, 0, 2, 0, 2, 0, 2, 0, 0 }
    };

    // Call the KnightInGeekland function with the
    // provided input
    int result
        = KnightInGeekland(start_x, start_y, arr);

    // Output the result
    Console.WriteLine(
        "The maximum score starting from the given position is: "
        + result);
}

}

// This code is contributed by Susobhan Akhuli

JavaScript

// JavaScript equivalent of the given Java code

// Function to find the maximum score starting from the given position function knightInGeekland(start_x, start_y, arr) { const n = arr.length; // number of rows const m = arr[0].length; // number of columns

const vis = Array.from({ length: n }, () => Array(m).fill(0)); // create a visited matrix to keep track of visited positions
vis[start_x][start_y] = 1; // mark the starting position as visited

const q = []; // create a queue to perform breadth-first search
q.push([start_x, start_y]); // push the starting position into the queue

const list = []; // create a list to store the score obtained at each level
let points = 0; // initialize the points to 0

const dx = [-2, -1, 1, 2, 2, 1, -1, -2]; // array to store possible x-direction moves
const dy = [1, 2, 2, 1, -1, -2, -2, -1]; // array to store possible y-direction moves

// Helper function to check if the given position is safe or not
const isSafe = (pos) => pos[0] >= 0 && pos[1] >= 0 && pos[0] < n && pos[1] < m;

while (q.length > 0) { // while the queue is not empty
    const size = q.length; // get the current size of the queue
    points = 0; // reset the points for each level

    for (let i = 0; i < size; i++) { // process all the elements in the current level
        const tmp = q.shift(); // get the front element
        const x = tmp[0], y = tmp[1]; // get the x and y coordinates

        points += arr[x][y]; // add the score at the current position to the points

        // check all possible moves from the current position
        for (let k = 0; k < 8; k++) {
            const xi = x + dx[k]; // get the new x coordinate
            const xj = y + dy[k]; // get the new y coordinate

            // if the new position is safe and not visited, mark it as visited and push it into the queue
            if (isSafe([xi, xj]) && vis[xi][xj] === 0) {
                vis[xi][xj] = 1; // mark the new position as visited
                q.push([xi, xj]); // push the new position into the queue
            }
        }
    }
    list.push(points); // add the points obtained at the current level to the list
}

// iterate backward through the list
for (let i = list.length - 1; i >= 0; i--) {
    if (list[i] + i < list.length) {
        list[i] += list[i + list[i]];
    }
}

let max = -1, ans = -1; // variables to store the maximum score and the answer position

// find the maximum score and its position
for (let i = 0; i < list.length; i++) {
    if (list[i] > max) {
        max = list[i]; // update the maximum score
        ans = i; // update the answer position
    }
}
return ans; // return the answer position

}

// Provided input const n = 9, m = 10; const start_x = 4, start_y = 5; const arr = [ [0, 0, 0, 2, 0, 2, 0, 2, 0, 0], [0, 0, 2, 0, 2, 0, 2, 0, 2, 0], [0, 2, 0, 0, 1, 2, 0, 0, 0, 2], [0, 0, 2, 0, 2, 0, 2, 0, 2, 0], [0, 2, 0, 2, 0, 0, 0, 2, 0, 2], [0, 0, 2, 0, 2, 0, 2, 0, 2, 0], [0, 2, 0, 0, 0, 2, 0, 0, 0, 2], [0, 0, 2, 0, 2, 0, 2, 0, 2, 0], [0, 0, 0, 2, 0, 2, 0, 2, 0, 0] ];

// Call the knightInGeekland function with the provided input const result = knightInGeekland(start_x, start_y, arr);

// Output the result console.log("The maximum score starting from the given position is: " + result);

`

Output

The maximum score starting from the given position is: 1

**Time Complexity: O(N*M) The breadth-first search (BFS) explores each cell at most once, where N is the number of rows and M is the number of columns in the grid.
**Auxiliary Space: O(N*M)