Open In App

Minimum queens required to cover all the squares of a chess board

Improve
Improve
Like Article
Like
Save
Share
Report

Given the dimension of a chess board (N x M), determine the minimum number of queens required to cover all the squares of the board. A queen can attack any square along its row, column or diagonals. 

Examples:

Input : N = 8, M = 8
Output : 5
Layout : Q X X X X X X X
X X Q X X X X X
X X X X Q X X X
X Q X X X X X X
X X X Q X X X X
X X X X X X X X
X X X X X X X X
X X X X X X X X

Input : N = 3, M = 5
Output : 2
Layout : Q X X X X
X X X X X
X X X Q X

This article attempts to solve the problem in a very simple way without much optimization.

  • Step 1: Starting from any corner square of the board, find an ‘uncovered’ square (Uncovered square is a square which isn’t attacked by any of the queens already placed). If none found, goto Step 4. 
  • Step 2: Place a Queen on this square and increment variable ‘count’ by 1. 
  • Step 3: Repeat step 1. 
  • Step 4: Now, you’ve got a layout where every square is covered. Therefore, the value of ‘count’ can be the answer. However, you might be able to do better, as there might exist a better layout with lesser number of queens. So, store this ‘count’ as the best value till now and proceed to find a better solution. 
  • Step 5: Remove the last queen placed and place it in the next ‘uncovered’ cell. Step 6: Proceed recursively and try out all the possible layouts. Finally, the one with the least number of queens is the answer.

Implementation: Dry run the following code for better understanding. 

C++




#include <bits/stdc++.h>
using namespace std;
// The chessboard is represented by a 2D array.
bool board[8][8];
// N x M is the dimension of the chess board.
const int N = 8, M = 8;
// The minimum number of queens required.
// Initially, set to MAX_VAL.
int minCount = INT_MAX;
string layout; // Stores the best layout.
// Stores the current layout in 'layout'
// variable as String.
void storeLayout()
{
    stringstream ss;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < M; j++)
            ss << (board[i][j] ? "Q " : "X ");
        ss << "\n";
    }
    layout = ss.str();
}
 
// Returns 'true' if the square (row, col) is
// being attacked by at least one queen.
bool isAttacked(int row, int col)
{
    int i, j;
 
    // Check the 'col'th column for any queen.
    for (i = 0; i < N; ++i)
        if (board[i][col])
            return true;
 
    // Check the 'row'th row for any queen.
    for (j = 0; j < M; ++j)
        if (board[row][j])
            return true;
 
    // Check the diagonals for any queen.
    for (i = 0; i < min(N, M); ++i)
        if (row - i >= 0 && col - i >= 0
            && board[row - i][col - i])
            return true;
        else if (row - i >= 0 && col + i < M
                 && board[row - i][col + i])
            return true;
        else if (row + i < N && col - i >= 0
                 && board[row + i][col - i])
            return true;
        else if (row + i < N && col + i < M
                 && board[row + i][col + i])
            return true;
 
    // This square is unattacked. Hence return 'false'.
    return false;
}
 
// Finds minimum count of queens needed and places them.
void placeQueen(int countSoFar)
{
    int i, j;
 
    if (countSoFar >= minCount)
 
        // We've already obtained a solution with lesser or
        // same number of queens. Hence, no need to proceed.
        return;
 
    bool flag = false;
    while (!flag) {
        for (i = 0; i < N; ++i)
            for (j = 0; j < M; ++j) {
                if (!isAttacked(i, j)) {
                    i = N;
                    flag = true;
                    break;
                }
            }
        if (flag)
            break;
 
        // All squares all covered. Hence, this
        // is the best solution till now.
        minCount = countSoFar;
        storeLayout();
        break;
    }
    // Checks if there exists any unattacked cells.
    for (i = 0; i < N; ++i)
        for (j = 0; j < M; ++j) {
            if (!isAttacked(i, j)) {
                // Square (i, j) is unattacked.
                // Therefore, place a queen here.
                board[i][j] = true;
 
                // Increment 'count' and proceed
                // recursively.
                placeQueen(countSoFar + 1);
 
                // Remove this queen and attempt to
                // find a better solution.
                board[i][j] = false;
            }
        }
}
 
// Driver code
int main()
{
    memset(board, false, sizeof(board));
    placeQueen(0);
 
    cout << minCount << endl;
    cout << "\nLayout: \n" << layout;
}


Java




// Java program to find minimum number of queens needed
// to cover a given chess board.
 
public class Backtracking {
 
    // The chessboard is represented by a 2D array.
    static boolean[][] board;
 
    // N x M is the dimension of the chess board.
    static int N, M;
 
    // The minimum number of queens required.
    // Initially, set to MAX_VAL.
    static int minCount = Integer.MAX_VALUE;
 
    static String layout; // Stores the best layout.
 
    // Driver code
    public static void main(String[] args)
    {
        N = 8;
        M = 8;
        board = new boolean[N][M];
        placeQueen(0);
 
        System.out.println(minCount);
        System.out.println("\nLayout: \n" + layout);
    }
 
    // Finds minimum count of queens needed and places them.
    static void placeQueen(int countSoFar)
    {
        int i, j;
 
        if (countSoFar >= minCount)
 
            // We've already obtained a solution with lesser
            // or same number of queens. Hence, no need to
            // proceed.
            return;
 
    // Checks if there exists any unattacked cells.
    findUnattackedCell : {
        for (i = 0; i < N; ++i)
            for (j = 0; j < M; ++j)
                if (!isAttacked(i, j))
 
                    // Square (i, j) is unattacked.
                    break findUnattackedCell;
 
        // All squares all covered. Hence, this
        // is the best solution till now.
        minCount = countSoFar;
        storeLayout();
 
        return;
    }
 
        for (i = 0; i < N; ++i)
            for (j = 0; j < M; ++j) {
                if (!isAttacked(i, j)) {
 
                    // Square (i, j) is unattacked.
                    // Therefore, place a queen here.
                    board[i][j] = true;
 
                    // Increment 'count' and proceed
                    // recursively.
                    placeQueen(countSoFar + 1);
 
                    // Remove this queen and attempt to
                    // find a better solution.
                    board[i][j] = false;
                }
            }
    }
 
    // Returns 'true' if the square (row, col) is
    // being attacked by at least one queen.
    static boolean isAttacked(int row, int col)
    {
        int i, j;
 
        // Check the 'col'th column for any queen.
        for (i = 0; i < N; ++i)
            if (board[i][col])
                return true;
 
        // Check the 'row'th row for any queen.
        for (j = 0; j < M; ++j)
            if (board[row][j])
                return true;
 
        // Check the diagonals for any queen.
        for (i = 0; i < Math.min(N, M); ++i)
            if (row - i >= 0 && col - i >= 0
                && board[row - i][col - i])
                return true;
            else if (row - i >= 0 && col + i < M
                     && board[row - i][col + i])
                return true;
            else if (row + i < N && col - i >= 0
                     && board[row + i][col - i])
                return true;
            else if (row + i < N && col + i < M
                     && board[row + i][col + i])
                return true;
 
        // This square is unattacked. Hence return 'false'.
        return false;
    }
 
    // Stores the current layout in 'layout'
    // variable as String.
    static void storeLayout()
    {
        StringBuilder sb = new StringBuilder();
        for (boolean[] row : board) {
            for (boolean cell : row)
                sb.append(cell ? "Q " : "X ");
            sb.append("\n");
        }
        layout = sb.toString();
    }
}


Python3




# The chessboard is represented by a 2D array.
board = [[False] * 8 for _ in range(8)]
# N x M is the dimension of the chess board.
N, M = 8, 8
# The minimum number of queens required.
# Initially, set to MAX_VALUE.
minCount = float('inf')
layout = ""  # Stores the best layout.
 
 
# Stores the current layout in 'layout'
# variable as String.
def storeLayout():
    global layout
    str_layout = ""
    for i in range(N):
        for j in range(M):
            if board[i][j]:
                str_layout += "Q "
            else:
                str_layout += "X "
        str_layout += "\n"
    layout = str_layout
 
 
# Returns 'True' if the square (row, col) is
# being attacked by at least one queen.
def isAttacked(row, col):
    # Check the 'col'th column for any queen.
    for i in range(N):
        if board[i][col]:
            return True
 
    # Check the 'row'th row for any queen.
    for j in range(M):
        if board[row][j]:
            return True
 
    # Check the diagonals for any queen.
    for i in range(min(N, M)):
        if row - i >= 0 and col - i >= 0 and board[row - i][col - i]:
            return True
        elif row - i >= 0 and col + i < M and board[row - i][col + i]:
            return True
        elif row + i < N and col - i >= 0 and board[row + i][col - i]:
            return True
        elif row + i < N and col + i < M and board[row + i][col + i]:
            return True
    return False
 
 
# Finds minimum count of queens needed and places them.
def placeQueen(countSoFar):
    global minCount
    if countSoFar >= minCount:
        # We've already obtained a solution with lesser or
        # same number of queens. Hence, no need to proceed.
        return
 
    flag = False
    while not flag:
        for i in range(N):
            for j in range(M):
                if not isAttacked(i, j):
                    i = N
                    flag = True
                    break
            if flag:
                break
        if flag:
            break
 
        # All squares are covered. Hence, this
        # is the best solution till now.
        minCount = countSoFar
        storeLayout()
        break
 
    # Checks if there exists any unattacked cells.
    for i in range(N):
        for j in range(M):
            if not isAttacked(i, j):
                # Square (i, j) is unattacked.
                # Therefore, place a queen here.
                board[i][j] = True
 
                # Increment 'count' and proceed
                # recursively.
                placeQueen(countSoFar + 1)
 
                # Remove this queen and attempt to
                # find a better solution.
                board[i][j] = False
 
 
# Driver code
placeQueen(0)
 
print(minCount)
print("\nLayout: \n" + layout)


C#




using System;
using System.Text;
 
class Program {
    // The chessboard is represented by a 2D array
    static bool[, ] board = new bool[8, 8];
    // N * M is the dimension of the chess board
    const int N = 8, M = 8;
    // The minimum number of queens required.
    // Initially, set to MAX_VALUE.
    static int minCount = int.MaxValue;
    // Stores the best layout.
    static string layout;
    // Stores the current layout in 'layout'
    // variable as String.
    static void StoreLayout()
    {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                sb.Append(board[i, j] ? "Q " : "X ");
            }
            sb.Append("\n");
        }
        layout = sb.ToString();
    }
    // Returns 'true' if the square (row, col) is
    // being attacked by at least one queen.
    static bool IsAttacked(int row, int col)
    {
        int i, j;
        // Check the 'col'th column for any queen.
        for (i = 0; i < N; ++i) {
            if (board[i, col])
                return true;
        }
        // Check the 'row'th row for any queen.
        for (j = 0; j < M; ++j) {
            if (board[row, j])
                return true;
        }
        // Check the diagonals for any queen.
        for (i = 0; i < Math.Min(N, M); ++i) {
            if (row - i >= 0 && col - i >= 0
                && board[row - i, col - i])
                return true;
            else if (row - i >= 0 && col + i < M
                     && board[row - i, col + i])
                return true;
            else if (row + i < N && col - i >= 0
                     && board[row + i, col - i])
                return true;
            else if (row + i < N && col + i < M
                     && board[row + i, col + i])
                return true;
        }
        // This square is unattacked. Hence return 'false'.
        return false;
    }
    // Finds minimum count of queens needed and places them.
    static void PlaceQueen(int countSoFar)
    {
        int i, j;
        // We've already obtained a solution with lesser or
        // same number of queens. Hence, no need to proceed.
        if (countSoFar >= minCount)
            return;
        bool flag = false;
        while (!flag) {
            for (i = 0; i < N; ++i) {
                for (j = 0; j < M; ++j) {
                    if (!IsAttacked(i, j)) {
                        i = N;
                        flag = true;
                        break;
                    }
                }
                if (flag)
                    break;
            }
            if (flag)
                break;
            // All squares all covered. Hence, this
            // is the best solution till now.
            minCount = countSoFar;
            StoreLayout();
            break;
        }
        // Checks if there exists any unattacked cells.
        for (i = 0; i < N; ++i) {
            for (j = 0; j < M; ++j) {
                if (!IsAttacked(i, j)) {
                    // Square (i, j) is unattacked.
                    // Therefore, place a queen here.
                    board[i, j] = true;
                    // Increment 'count' and proceed
                    // recursively.
                    PlaceQueen(countSoFar + 1);
                    // Remove this queen and attempt to
                    // find a better solution.
                    board[i, j] = false;
                }
            }
        }
    }
 
    static void Main()
    {
        Array.Clear(board, 0, board.Length);
        PlaceQueen(0);
        Console.WriteLine(minCount);
        Console.WriteLine("\nLayout: \n" + layout);
    }
}


Javascript




// The chessboard is represented by a 2D array.
const board = Array.from(Array(8), () => new Array(8).fill(false));
 
// N x M is the dimension of the chess board.
const N = 8, M = 8;
 
// The minimum number of queens required.
// Initially, set to MAX_VALUE.
let minCount = Number.MAX_VALUE;
 
let layout = ""; // Stores the best layout.
 
// Stores the current layout in 'layout'
// variable as String.
function storeLayout() {
    let str = "";
    for (let i = 0; i < N; i++) {
        for (let j = 0; j < M; j++) {
            if (board[i][j]) {
                str += "Q ";
            } else {
                str += "X ";
            }
        }
        str += "\n";
    }
    layout = str;
}
 
// Returns 'true' if the square (row, col) is
// being attacked by at least one queen.
function isAttacked(row, col) {
    let i, j;
     
    // Check the 'col'th column for any queen.
    for (i = 0; i < N; ++i) {
        if (board[i][col]) {
            return true;
        }
    }
     
    // Check the 'row'th row for any queen.
    for (j = 0; j < M; ++j) {
        if (board[row][j]) {
            return true;
        }
    }
     
    // Check the diagonals for any queen.
    for (i = 0; i < Math.min(N, M); ++i) {
        if ( row - i >= 0 && col - i >= 0 && board[row - i][col - i]) {
            return true;
        } else if ( row - i >= 0 && col + i < M && board[row - i][col + i] ) {
            return true;
        } else if ( row + i < N && col - i >= 0 && board[row + i][col - i] ) {
            return true;
        } else if ( row + i < N && col + i < M && board[row + i][col + i] ) {
            return true;
        }
    }
     
    // This square is unattacked. Hence return 'false'.
    return false;
}
 
// Finds minimum count of queens needed and places them.
function placeQueen(countSoFar) {
    let i, j;
     
    if (countSoFar >= minCount) {
        // We've already obtained a solution with lesser or
        // same number of queens. Hence, no need to proceed.
        return;
    }
     
    let flag = false;
    while (!flag) {
        for (i = 0; i < N; ++i) {
            for (j = 0; j < M; ++j) {
                if (!isAttacked(i, j)) {
                    i = N;
                    flag = true;
                    break;
                }
            }
            if (flag) {
                break;
            }
        }
        if (flag) {
            break;
        }
         
        // All squares are covered. Hence, this
        // is the best solution till now.
        minCount = countSoFar;
        storeLayout();
        break;
    }
    // Checks if there exists any unattacked cells.
    for (i = 0; i < N; ++i) {
        for (j = 0; j < M; ++j) {
            if (!isAttacked(i, j)) {
                // Square (i, j) is unattacked.
                // Therefore, place a queen here.
                board[i][j] = true;
         
                // Increment 'count' and proceed
                // recursively.
                placeQueen(countSoFar + 1);
         
                // Remove this queen and attempt to
                // find a better solution.
                board[i][j] = false;
            }
        }
    }
}
 
// Driver code
placeQueen(0);
 
console.log(minCount);
console.log("\nLayout: \n" + layout);


Output

5

Layout: 
Q X X X X X X X 
X X Q X X X X X 
X X X X Q X X X 
X Q X X X X X X 
X X X Q X X X X 
X X X X X X X X 
X X X X X X X X 
X X X X X X X X


Last Updated : 26 Feb, 2024
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads