Open In App

CSES Solutions – Chessboard and Queens

Last Updated : 27 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Your task is to place eight queens on a chessboard so that no two queens are attacking each other. As an additional challenge, each square is either free or reserved, and you can only place queens on the free squares. However, the reserved squares do not prevent queens from attacking each other. How many possible ways are there to place the queens?

queens

Examples:

Input:
……..
……..
..*…..
……..
……..
…..**.
…*….
……..
Output: 65
Explanation: There are 65 ways to place eight queens such that no two queens attack each other.

Input:
********
********
********
********
********
********
********
********

Output: 0
Explanation: There is no space to put eight queens that do not attack each other.

Approach: To solve the problem, follow the below idea:

The problem can be solved using Recursion and checking by placing queens at every possible row and column. We can start from the first row and then try to place queen in every column. Every time we place a queen in any row, we move to the next row and start placing another queen in that row. To efficiently check whether two queens are attacking each other, we can maintain three boolean arrays:

  • occupiedCol[i] = true if there is a queen somewhere in the column i.
  • occupiedPrimary[i] = true if there is a queen across the primary diagonal having (row + column = i). Value of (row + column) is same for all the cells lying on the same primary diagonal.
  • occupiedSecondary[i] = true if there is a queen across the secondary diagonal having (row – column + 8 = i). Value of (row – column + 8 ) is same for all the cells lying on the same secondary diagonal.

Step-by-step algorithm:

  • Maintain a function solve(row) to calculate the number of ways to place queens, if we are currently at row = row.
  • If we have reached the end of the board, increment answer by 1.
  • Check if we can place a queen at the current cell or not.
  • For each row, traverse through all the columns and try to place a queen in all the cells.
  • After putting the queen, move to the next row and try to place a queen in it.
  • After counting all the paths, return the final answer.

Below is the implementation of the algorithm:

C++
#include <bits/stdc++.h>
using namespace std;

void solve(vector<string>& board, int row,
        vector<bool>& occupiedCol,
        vector<bool>& occupiedPrimary,
        vector<bool>& occupiedSecondary, int& ans)
{
    if (row == 8) {
        ans += 1;
        return;
    }
    for (int col = 0; col < 8; col++) {
        if (board[row][col] == '*' || occupiedCol[col]
            || occupiedPrimary[row - col + 8]
            || occupiedSecondary[row + col]) {
            continue;
        }
        occupiedCol[col] = occupiedPrimary[row - col + 8]
            = occupiedSecondary[row + col] = true;
        solve(board, row + 1, occupiedCol, occupiedPrimary,
            occupiedSecondary, ans);
        occupiedCol[col] = occupiedPrimary[row - col + 8]
            = occupiedSecondary[row + col] = false;
    }
}

int main()
{
    vector<string> board = { "........", "........",
                            "..*.....", "........",
                            "........", ".....**.",
                            "...*....", "........" };
    vector<bool> occupiedCol(10, false),
        occupiedPrimary(20, false),
        occupiedSecondary(20, false);

    int ans = 0;
    solve(board, 0, occupiedCol, occupiedPrimary,
        occupiedSecondary, ans);
    cout << ans << "\n";
}
Java
import java.util.Arrays;
import java.util.List;

public class EightQueens {

    // Function to solve the N-Queens problem
    static void solve(List<String> board, int row,
                      boolean[] occupiedCol,
                      boolean[] occupiedPrimary,
                      boolean[] occupiedSecondary, int[] ans) {
        // Base case: If all queens are placed, increment the solution count
        if (row == 8) {
            ans[0]++;
            return;
        }

        // Try placing the queen in each column of the current row
        for (int col = 0; col < 8; col++) {
            // Check if the current position is safe for the queen
            if (board.get(row).charAt(col) == '*' || occupiedCol[col]
                || occupiedPrimary[row - col + 8]
                || occupiedSecondary[row + col]) {
                continue; // Skip if not safe
            }

            // Place the queen and mark the occupied positions
            occupiedCol[col] = occupiedPrimary[row - col + 8]
                = occupiedSecondary[row + col] = true;

            // Recursively move to the next row
            solve(board, row + 1, occupiedCol, occupiedPrimary,
                  occupiedSecondary, ans);

            // Backtrack: Reset the occupied positions for the current queen placement
            occupiedCol[col] = occupiedPrimary[row - col + 8]
                = occupiedSecondary[row + col] = false;
        }
    }

    public static void main(String[] args) {
        List<String> board = Arrays.asList(
                "........",
                "........",
                "..*.....",
                "........",
                "........",
                ".....**.",
                "...*....",
                "........"
        );

        boolean[] occupiedCol = new boolean[8];
        boolean[] occupiedPrimary = new boolean[16];
        boolean[] occupiedSecondary = new boolean[16];

        int[] ans = {0}; // Using an array to store the solution count

        // Call the solve function to find the number of solutions
        solve(board, 0, occupiedCol, occupiedPrimary,
              occupiedSecondary, ans);

        System.out.println(ans[0]);
    }
}

// This code is contributed by shivamgupta310570
Python
def solve(board, row, occupiedCol, occupiedPrimary, occupiedSecondary, ans):
    if row == 8:
        ans[0] += 1
        return
    for col in range(8):
        if board[row][col] == '*' or occupiedCol[col] or occupiedPrimary[row - col + 8] or occupiedSecondary[row + col]:
            continue
        occupiedCol[col] = occupiedPrimary[row - col + 8] = occupiedSecondary[row + col] = True
        solve(board, row + 1, occupiedCol, occupiedPrimary, occupiedSecondary, ans)
        occupiedCol[col] = occupiedPrimary[row - col + 8] = occupiedSecondary[row + col] = False

board = [ "........",
          "........",
          "..*.....",
          "........",
          "........",
          ".....**.",
          "...*....",
          "........" ]

occupiedCol = [False] * 10
occupiedPrimary = [False] * 20
occupiedSecondary = [False] * 20
ans = [0]

solve(board, 0, occupiedCol, occupiedPrimary, occupiedSecondary, ans)
print(ans[0])
C#
using System;
using System.Collections.Generic;

public class EightQueens
{
    // Function to solve the N-Queens problem
    static void Solve(List<string> board, int row,
                      bool[] occupiedCol,
                      bool[] occupiedPrimary,
                      bool[] occupiedSecondary, int[] ans)
    {
        // Base case: If all queens are placed, increment the solution count
        if (row == 8)
        {
            ans[0]++;
            return;
        }

        // Try placing the queen in each column of the current row
        for (int col = 0; col < 8; col++)
        {
            // Check if the current position is safe for the queen
            if (board[row][col] == '*' || occupiedCol[col]
                || occupiedPrimary[row - col + 8]
                || occupiedSecondary[row + col])
            {
                continue; // Skip if not safe
            }

            // Place the queen and mark the occupied positions
            occupiedCol[col] = occupiedPrimary[row - col + 8]
                = occupiedSecondary[row + col] = true;

            // Recursively move to the next row
            Solve(board, row + 1, occupiedCol, occupiedPrimary,
                  occupiedSecondary, ans);

            // Backtrack: Reset the occupied positions for the current queen placement
            occupiedCol[col] = occupiedPrimary[row - col + 8]
                = occupiedSecondary[row + col] = false;
        }
    }

    public static void Main(string[] args)
    {
        List<string> board = new List<string>
        {
            "........",
            "........",
            "..*.....",
            "........",
            "........",
            ".....**.",
            "...*....",
            "........"
        };

        bool[] occupiedCol = new bool[8];
        bool[] occupiedPrimary = new bool[16];
        bool[] occupiedSecondary = new bool[16];

        int[] ans = {0}; // Using an array to store the solution count

        // Call the Solve function to find the number of solutions
        Solve(board, 0, occupiedCol, occupiedPrimary,
              occupiedSecondary, ans);

        Console.WriteLine(ans[0]);
    }
}
JavaScript
// Function to solve the problem
function solve(board, row, occupiedCol, occupiedPrimary, occupiedSecondary) {
    // If the row is 8, increment the answer by 1 and return
    if (row === 8) {
        return 1;
    }
    let ans = 0;
    // Iterate over each column
    for (let col = 0; col < 8; col++) {
        // If the current cell is occupied or the current column or diagonals are occupied, continue to the next column
        if (board[row][col] === '*' || occupiedCol[col] || occupiedPrimary[row - col + 8] || occupiedSecondary[row + col]) {
            continue;
        }
        // Mark the current column and diagonals as occupied
        occupiedCol[col] = occupiedPrimary[row - col + 8] = occupiedSecondary[row + col] = true;
        // Recursively call the solve function for the next row and add the result to the answer
        ans += solve(board, row + 1, occupiedCol, occupiedPrimary, occupiedSecondary);
        // Unmark the current column and diagonals
        occupiedCol[col] = occupiedPrimary[row - col + 8] = occupiedSecondary[row + col] = false;
    }
    // Return the answer
    return ans;
}

// Main function
function main() {
    // Initialize the board
    const board = ["........", "........", "..*.....", "........", "........", ".....**.", "...*....", "........"];
    // Initialize the occupied columns and diagonals
    const occupiedCol = Array(10).fill(false);
    const occupiedPrimary = Array(20).fill(false);
    const occupiedSecondary = Array(20).fill(false);
    // Call the solve function and print the result
    console.log(solve(board, 0, occupiedCol, occupiedPrimary, occupiedSecondary));
}

// Call the main function
main();

Output
65

Time Complexity: O(N!), where N is the size of chessboard.
Auxiliary Space: O(N)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads