Open In App

Place K-knights such that they do not attack each other

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

Given integers M, N and K, the task is to place K knights on an M*N chessboard such that they don’t attack each other. The knights are expected to be placed on different squares on the board. A knight can move two squares vertically and one square horizontally or two squares horizontally and one square vertically. The knights attack each other if one of them can reach the other in single move. There are multiple ways of placing K knights on an M*N board or sometimes, no way of placing them. We are expected to list out all the possible solutions. 

Examples:

Input: M = 3, N = 3, K = 5 Output: K A K A K A K A K A K A K K K A K A Total number of solutions : 2  

Input: M = 5, N = 5, K = 13 Output: K A K A K A K A K A K A K A K A K A K A K A K A K Total number of solutions : 1

Approach: This problem can be solved using backtracking. The idea is to place the knights one by one starting from first row and first column and moving forward to first row and second column such that they don’t attack each other. When one row gets over, we move to the next row. Before placing a knight, we always check if the block is safe i.e. it is not an attacking position of some other knight. If it is safe, we place the knight and mark it’s attacking position on the board else we move forward and check for other blocks. While following this procedure, we make a new board every time we insert a new knight into our board. This is done because if we get one solution and we need other solutions, then we can backtrack to our old board with old configuration of knights which can then be checked for other possible solutions. The process of backtracking is continued till we get all our possible solutions. Below is the implementation of the above approach: 

CPP




// C++ implementation of the above approach
#include <iostream>
using namespace std;
 
/* m*n is the board dimension
k is the number of knights to be placed on board
count is the number of possible solutions */
int m, n, k;
int count = 0;
 
/* This function is used to create an empty m*n board */
void makeBoard(char** board)
{
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            board[i][j] = '_';
        }
    }
}
 
/* This function displays our board */
void displayBoard(char** board)
{
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            cout << " " << board[i][j] << " ";
        }
        cout << endl;
    }
    cout << endl;
}
 
/* This function marks all the attacking
position of a knight placed at board[i][j]
position */
void attack(int i, int j, char a, char** board)
{
 
    /* conditions to ensure that the
    block to be checked is inside the board */
    if ((i + 2) < m && (j - 1) >= 0) {
        board[i + 2][j - 1] = a;
    }
    if ((i - 2) >= 0 && (j - 1) >= 0) {
        board[i - 2][j - 1] = a;
    }
    if ((i + 2) < m && (j + 1) < n) {
        board[i + 2][j + 1] = a;
    }
    if ((i - 2) >= 0 && (j + 1) < n) {
        board[i - 2][j + 1] = a;
    }
    if ((i + 1) < m && (j + 2) < n) {
        board[i + 1][j + 2] = a;
    }
    if ((i - 1) >= 0 && (j + 2) < n) {
        board[i - 1][j + 2] = a;
    }
    if ((i + 1) < m && (j - 2) >= 0) {
        board[i + 1][j - 2] = a;
    }
    if ((i - 1) >= 0 && (j - 2) >= 0) {
        board[i - 1][j - 2] = a;
    }
}
 
/* If the position is empty,
place the knight */
bool canPlace(int i, int j, char** board)
{
    if (board[i][j] == '_')
        return true;
    else
        return false;
}
 
/* Place the knight at [i][j] position
on board */
void place(int i, int j, char k, char a, char** board,
           char** new_board)
{
 
    /* Copy the configurations of
    old board to new board */
    for (int y = 0; y < m; y++) {
        for (int z = 0; z < n; z++) {
            new_board[y][z] = board[y][z];
        }
    }
 
    /* Place the knight at [i][j]
    position on new board */
    new_board[i][j] = k;
 
    /* Mark all the attacking positions
    of newly placed knight on the new board */
    attack(i, j, a, new_board);
}
 
/* Function for placing knights on board
such that they don't attack each other */
void kkn(int k, int sti, int stj, char** board)
{
 
    /* If there are no knights left to be placed,
    display the board and increment the count */
    if (k == 0) {
        displayBoard(board);
        count++;
    }
    else {
 
        /* Loop for checking all the
positions on m*n board */
        for (int i = sti; i < m; i++) {
            for (int j = stj; j < n; j++) {
 
                /* Is it possible to place knight at
[i][j] position on board? */
                if (canPlace(i, j, board)) {
 
                    /* Create a new board and place the
                    new knight on it */
                    char** new_board = new char*[m];
                    for (int x = 0; x < m; x++) {
                        new_board[x] = new char[n];
                    }
                    place(i, j, 'K', 'A', board, new_board);
 
                    /* Call the function recursively for
                    (k-1) leftover knights */
                    kkn(k - 1, i, j, new_board);
 
                    /* Delete the new board
                    to free up the memory */
                    for (int x = 0; x < m; x++) {
                        delete[] new_board[x];
                    }
                    delete[] new_board;
                }
            }
            stj = 0;
        }
    }
}
 
// Driver code
int main()
{
    m = 4, n = 3, k = 6;
 
    /* Creation of a m*n board */
    char** board = new char*[m];
    for (int i = 0; i < m; i++) {
        board[i] = new char[n];
    }
 
    /* Make all the places are empty */
    makeBoard(board);
 
    kkn(k, 0, 0, board);
 
    cout << endl << "Total number of solutions : " << count;
    return 0;
}


Java




// Java implementation of the above approach
 
class GFG {
 
    /* m*n is the board dimension
    k is the number of knights to be placed on board
    count is the number of possible solutions */
    static int m, n, k;
    static int count = 0;
 
    /* This function is used to create an empty m*n board */
    static void makeBoard(char[][] board)
    {
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                board[i][j] = '_';
            }
        }
    }
 
    /* This function displays our board */
    static void displayBoard(char[][] board)
    {
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                System.out.print(" " + board[i][j] + " ");
            }
            System.out.println();
        }
        System.out.println();
    }
 
    /* This function marks all the attacking
    position of a knight placed at board[i][j]
    position */
    static void attack(int i, int j, char a, char[][] board)
    {
 
        /* conditions to ensure that the
        block to be checked is inside the board */
        if ((i + 2) < m && (j - 1) >= 0) {
            board[i + 2][j - 1] = a;
        }
        if ((i - 2) >= 0 && (j - 1) >= 0) {
            board[i - 2][j - 1] = a;
        }
        if ((i + 2) < m && (j + 1) < n) {
            board[i + 2][j + 1] = a;
        }
        if ((i - 2) >= 0 && (j + 1) < n) {
            board[i - 2][j + 1] = a;
        }
        if ((i + 1) < m && (j + 2) < n) {
            board[i + 1][j + 2] = a;
        }
        if ((i - 1) >= 0 && (j + 2) < n) {
            board[i - 1][j + 2] = a;
        }
        if ((i + 1) < m && (j - 2) >= 0) {
            board[i + 1][j - 2] = a;
        }
        if ((i - 1) >= 0 && (j - 2) >= 0) {
            board[i - 1][j - 2] = a;
        }
    }
 
    /* If the position is empty,
    place the knight */
    static boolean canPlace(int i, int j, char[][] board)
    {
        if (board[i][j] == '_')
            return true;
        else
            return false;
    }
 
    /* Place the knight at [i][j] position
    on board */
    static void place(int i, int j, char k, char a,
                      char[][] board, char[][] new_board)
    {
 
        /* Copy the configurations of
        old board to new board */
        for (int y = 0; y < m; y++) {
            for (int z = 0; z < n; z++) {
                new_board[y][z] = board[y][z];
            }
        }
 
        /* Place the knight at [i][j]
        position on new board */
        new_board[i][j] = k;
 
        /* Mark all the attacking positions
        of newly placed knight on the new board */
        attack(i, j, a, new_board);
    }
 
    /* Function for placing knights on board
    such that they don't attack each other */
    static void kkn(int k, int sti, int stj, char[][] board)
    {
 
        /* If there are no knights left to be placed,
        display the board and increment the count */
        if (k == 0) {
            displayBoard(board);
            count++;
        }
        else {
 
            /* Loop for checking all the
    positions on m*n board */
            for (int i = sti; i < m; i++) {
                for (int j = stj; j < n; j++) {
 
                    /* Is it possible to place knight at
    [i][j] position on board? */
                    if (canPlace(i, j, board)) {
 
                        /* Create a new board and place
                        the new knight on it */
                        char[][] new_board = new char[m][];
                        for (int x = 0; x < m; x++) {
                            new_board[x] = new char[n];
                        }
                        place(i, j, 'K', 'A', board,
                              new_board);
 
                        /* Call the function recursively for
                        (k-1) leftover knights */
                        kkn(k - 1, i, j, new_board);
                    }
                }
                stj = 0;
            }
        }
    }
 
    // Driver code
    public static void main(String[] args)
    {
        m = 4;
        n = 3;
        k = 6;
        count = 0;
 
        /* Creation of a m*n board */
        char[][] board = new char[m][];
        for (int i = 0; i < m; i++) {
            board[i] = new char[n];
        }
 
        /* Make all the places are empty */
        makeBoard(board);
 
        kkn(k, 0, 0, board);
 
        System.out.println("\n Total number of solutions : "
                           + count);
    }
}
 
// This code is contributed by jainlovely450


Python3




# Python Code for the above approach
m, n, k = 4, 3, 6
count = 0
 
# This function is used to create an empty m*n board
def makeBoard(board):
    for i in range(m):
        for j in range(n):
            board[i][j] = '_'
 
# This function displays our board
def displayBoard(board):
    for i in range(m):
        for j in range(n):
            print(" ", board[i][j], " ", end="")
        print()
    print()
 
 
def attack(i, j, a, board):
    if (i + 2) < m and (j - 1) >= 0:
        board[i + 2][j - 1] = a
    if (i - 2) >= 0 and (j - 1) >= 0:
        board[i - 2][j - 1] = a
    if (i + 2) < m and (j + 1) < n:
        board[i + 2][j + 1] = a
    if (i - 2) >= 0 and (j + 1) < n:
        board[i - 2][j + 1] = a
    if (i + 1) < m and (j + 2) < n:
        board[i + 1][j + 2] = a
    if (i - 1) >= 0 and (j + 2) < n:
        board[i - 1][j + 2] = a
    if (i + 1) < m and (j - 2) >= 0:
        board[i + 1][j - 2] = a
    if (i - 1) >= 0 and (j - 2) >= 0:
        board[i - 1][j - 2] = a
 
def canPlace(i, j, board):
    if board[i][j] == '_':
        return True
    else:
        return False
 
def place(i, j, k, a, board, new_board):
   
    # Copy the configurations of old board to new board
    for y in range(m):
        for z in range(n):
            new_board[y][z] = board[y][z]
 
    # Place the knight at [i][j] position on new board
    new_board[i][j] = k
 
    # Mark all the attacking positions of newly placed knight on the new board
    attack(i, j, a, new_board)
 
# Function for placing knights on board such that they don't attack each other
def kkn(k, sti, stj, board):
   
    # If there are no knights left to be placed, display the board and increment the count
    if k == 0:
        displayBoard(board)
        global count
        count += 1
    else:
        # Loop for checking all the positions on m*n board
        for i in range(sti, m):
            for j in range(stj, n):
               
                # Is it possible to place knight at [i][j] position on board?
                if canPlace(i, j, board):
                   
                    # Create a new board and place the new knight on it
                    new_board = [[0 for x in range(n)] for y in range(m)]
                    place(i, j, 'K', 'A', board, new_board)
                     
                    # Call the function recursively for (k-1) leftover knights
                    kkn(k - 1, i, j, new_board)
                     
                    # Delete the new board to free up the memory
                    del new_board
            stj = 0
 
 
board = [[0 for x in range(n)] for y in range(m)]
 
# Make all the places are empty
makeBoard(board)
 
kkn(k, 0, 0, board)
 
print("Total number of solutions :", count)
 
# This code is contributed by ishankhandelwals.


C#




using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
 
class GFG {
    /* m*n is the board dimension
    k is the number of knights to be placed on board
    count is the number of possible solutions */
    static int m, n, k;
    static int count = 0;
 
    /* This function is used to create an empty m*n board */
    static void makeBoard(char[][] board)
    {
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                board[i][j] = '_';
            }
        }
    }
 
    /* This function displays our board */
    static void displayBoard(char[][] board)
    {
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                Console.Write(" " + board[i][j] + " ");
            }
            Console.WriteLine();
        }
        Console.WriteLine();
    }
 
    /* This function marks all the attacking
    position of a knight placed at board[i][j]
    position */
    static void attack(int i, int j, char a, char[][] board)
    {
 
        /* conditions to ensure that the
        block to be checked is inside the board */
        if ((i + 2) < m && (j - 1) >= 0) {
            board[i + 2][j - 1] = a;
        }
        if ((i - 2) >= 0 && (j - 1) >= 0) {
            board[i - 2][j - 1] = a;
        }
        if ((i + 2) < m && (j + 1) < n) {
            board[i + 2][j + 1] = a;
        }
        if ((i - 2) >= 0 && (j + 1) < n) {
            board[i - 2][j + 1] = a;
        }
        if ((i + 1) < m && (j + 2) < n) {
            board[i + 1][j + 2] = a;
        }
        if ((i - 1) >= 0 && (j + 2) < n) {
            board[i - 1][j + 2] = a;
        }
        if ((i + 1) < m && (j - 2) >= 0) {
            board[i + 1][j - 2] = a;
        }
        if ((i - 1) >= 0 && (j - 2) >= 0) {
            board[i - 1][j - 2] = a;
        }
    }
 
    /* If the position is empty,
    place the knight */
    static bool canPlace(int i, int j, char[][] board)
    {
        if (board[i][j] == '_')
            return true;
        else
            return false;
    }
 
    /* Place the knight at [i][j] position
      on board */
    static void place(int i, int j, char k, char a,
                      char[][] board, char[][] new_board)
    {
 
        /* Copy the configurations of
        old board to new board */
        for (int y = 0; y < m; y++) {
            for (int z = 0; z < n; z++) {
                new_board[y][z] = board[y][z];
            }
        }
 
        /* Place the knight at [i][j]
        position on new board */
        new_board[i][j] = k;
 
        /* Mark all the attacking positions
        of newly placed knight on the new board */
        attack(i, j, a, new_board);
    }
 
    /* Function for placing knights on board
    such that they don't attack each other */
    static void kkn(int k, int sti, int stj, char[][] board)
    {
 
        /* If there are no knights left to be placed,
        display the board and increment the count */
        if (k == 0) {
            displayBoard(board);
            count++;
        }
        else {
 
            /* Loop for checking all the
    positions on m*n board */
            for (int i = sti; i < m; i++) {
                for (int j = stj; j < n; j++) {
 
                    /* Is it possible to place knight at
    [i][j] position on board? */
                    if (canPlace(i, j, board)) {
 
                        /* Create a new board and place
                        the new knight on it */
                        char[][] new_board = new char[m][];
                        for (int x = 0; x < m; x++) {
                            new_board[x] = new char[n];
                        }
                        place(i, j, 'K', 'A', board,
                              new_board);
 
                        /* Call the function recursively for
                        (k-1) leftover knights */
                        kkn(k - 1, i, j, new_board);
                    }
                }
                stj = 0;
            }
        }
    }
 
    // Driver code
    public static void Main(String[] args)
    {
        m = 4;
        n = 3;
        k = 6;
        count = 0;
 
        /* Creation of a m*n board */
        char[][] board = new char[m][];
        for (int i = 0; i < m; i++) {
            board[i] = new char[n];
        }
 
        /* Make all the places are empty */
        makeBoard(board);
 
        kkn(k, 0, 0, board);
        Console.WriteLine("\n Total number of solutions : "
                          + count);
    }
}


Javascript




// JavaScript code for the above approach
let m, n, k;
let count = 0;
 
// This function is used to create an empty m*n board
function makeBoard(board) {
    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            board[i][j] = '_';
        }
    }
}
 
// This function displays our board
function displayBoard(board) {
    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            console.log(" " + board[i][j] + " ");
        }
        console.log("\n");
    }
    console.log("\n");
}
 
function attack(i, j, a, board) {
    if ((i + 2) < m && (j - 1) >= 0) {
        board[i + 2][j - 1] = a;
    }
    if ((i - 2) >= 0 && (j - 1) >= 0) {
        board[i - 2][j - 1] = a;
    }
    if ((i + 2) < m && (j + 1) < n) {
        board[i + 2][j + 1] = a;
    }
    if ((i - 2) >= 0 && (j + 1) < n) {
        board[i - 2][j + 1] = a;
    }
    if ((i + 1) < m && (j + 2) < n) {
        board[i + 1][j + 2] = a;
    }
    if ((i - 1) >= 0 && (j + 2) < n) {
        board[i - 1][j + 2] = a;
    }
    if ((i + 1) < m && (j - 2) >= 0) {
        board[i + 1][j - 2] = a;
    }
    if ((i - 1) >= 0 && (j - 2) >= 0) {
        board[i - 1][j - 2] = a;
    }
}
 
function canPlace(i, j, board) {
    if (board[i][j] === '_') {
        return true;
    } else {
        return false;
    }
}
 
function place(i, j, k, a, board, new_board) {
    // Copy the configurations of old board to new board
    for (let y = 0; y < m; y++) {
        for (let z = 0; z < n; z++) {
            new_board[y][z] = board[y][z];
        }
    }
 
    // Place the knight at [i][j] position on new board
    new_board[i][j] = k;
 
    // Mark all the attacking positions of newly placed knight on the new board
    attack(i, j, a, new_board);
}
 
//Function for placing knights on board such that they don't attack each other
function kkn(k, sti, stj, board) {
    //If there are no knights left to be placed, display the board and increment the count
    if (k == 0) {
        displayBoard(board);
        count++;
    }
    else {
        //Loop for checking all the positions on m*n board
        for (let i = sti; i < m; i++) {
            for (let j = stj; j < n; j++) {
                //Is it possible to place knight at [i][j] position on board?
                if (canPlace(i, j, board)) {
                    //Create a new board and place the new knight on it
                    let new_board = [];
                    for (let x = 0; x < m; x++) {
                        new_board[x] = [];
                    }
                    place(i, j, 'K', 'A', board, new_board);
                    //Call the function recursively for (k-1) leftover knights
                    kkn(k - 1, i, j, new_board);
                    //Delete the new board to free up the memory
                    for (let x = 0; x < m; x++) {
                        delete new_board[x];
                    }
                    delete new_board;
                }
            }
            stj = 0;
        }
    }
}
 
m = 4, n = 3, k = 6;
let board = [];
 
for (let i = 0; i < m; i++) {
    board[i] = new Array(n);
}
 
// Make all the places are empty
makeBoard(board);
 
kkn(k, 0, 0, board);
 
console.log(`Total number of solutions : ${count}`);
 
// This code is contributed by ishankhandelwals.


Output

 K  K  K 
 A  A  A 
 A  A  A 
 K  K  K 

 K  A  K 
 A  K  A 
 K  A  K 
 A  K  A 

 A  K  A 
 K  A  K 
 A  K  A 
 K  A  K 


Total number of solutions : 3

Time Complexity: O((mn)^k * k), where mn is the size of the board, k is the number of knights to be placed on the board.

Space Complexity: O(mnk) as it involves creating a new board for each recursive call to the kkn function.



Last Updated : 08 Mar, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads