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: 1Input: 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:
- Perform a breadth-first search (BFS) starting from the given position of the knight.
- At each step, calculate the score by adding the points in the current cell to the total points.
- Update the visited matrix to mark the current cell as visited.
- Explore all possible moves of the knight in L-shaped patterns, ensuring the moves are within the grid boundaries and the cells are not revisited.
- Continue BFS until all reachable cells are visited and accumulate the scores at each level.
- Iterate backward through the list of scores and update each score by adding the score at the next position.
- Find the maximum score and its corresponding position.
- Return the position as the minimum number of steps required to collect the maximum points.
Below is the implementation of the above approach:
#include <iostream> #include <queue> #include <vector> using namespace std;
// Function to find the maximum score starting from the // given position int knightInGeekland( int start_x, int start_y,
vector<vector< int > >& 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< 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
cout << "The maximum score starting from the given "
"position is: "
<< result << endl;
return 0;
} |
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);
}
} |
# 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# 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< int > > 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 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);
|
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)