Search code examples
algorithmbig-oasymptotic-complexityn-queens

More efficient algorithm to count attacks in N-queens?


I'm working on a DFS based solution to the N-queens problem.

I store the board state as an int[N] array representing the vertical placements of queens in each column (eg. placement of the queens diagonally down a 6x6 board would be state = { 0, 1, 2, 3, 4, 5 }), where -1 represents "no queen in this column".

My current algorithm for counting the queen attacks in a given state configuration has complexity of O(n^2):

function count_attacks(state)

    attack_count = 0

    for each column index c1
      if state[c1] == -1 continue

      for each column index c2 further along than c1
        if state[c2] == -1 continue

        // Lined up horizontally?
        if state[c1] == state[c2] attack_count++    

        // Lined up diagonally?
        else if (c2 - c1) == abs(state[c2] - state[c1]) attack_count++   

       // No need to check lined up vertically as impossible with this state representation

    return attack_count;

The O(N^2) kills performance when solving for say N=500+.

Is it possible to do better than O(N^2) for counting attacks?


Solution

  • Define arrays

    rows, columns, left_diagonals, right_diagonals
    

    which count respectively the number of queens in the i-th row, column, left diagonal (all x and y such that x-y=c for some c), right diagonal (all x and y such that x+y=c for some c). The algorithm would then be:

    Intialize rows, columns, left_diagonals, right_diagonals with zero values
    attacks = 0
    for queen in queens
        attacks += rows[queen.row];
        attacks += columns[queen.column];
        attacks += left_diagonals[queen.left_diagonal];
        attacks += right_diagonals[queen.right_diagonal];
        rows[queen.row]++;
        columns[queen.column]++;
        left_diagonals[queen.left_diagonal]++;
        right_diagonals[queen.right_diagonal]++;
    

    However, for solving the N queen problem you don't need to check the number of attacks. You just need to check if an attack exists.

    Also, if you are looking for a single solution of the problem there is a very efficient algorithm.