Open In App

N-Queen Problem | Local Search using Hill climbing with random neighbour

The N Queen is the problem of placing N chess queens on an N×N chessboard so that no two queens attack each other. 
For example, the following is a solution for 8 Queen problem.
 



Input: N = 4 
Output: 
0 1 0 0 
0 0 0 1 
1 0 0 0 
0 0 1 0 
Explanation: 
The Position of queens are: 
1 – {1, 2} 
2 – {2, 4} 
3 – {3, 1} 
4 – {4, 3}
As we can see that we have placed all 4 queens 
in a way that no two queens are attacking each other. 
So, the output is correct
 

Input: N = 8 
Output: 
0 0 0 0 0 0 1 0 
0 1 0 0 0 0 0 0 
0 0 0 0 0 1 0 0 
0 0 1 0 0 0 0 0 
1 0 0 0 0 0 0 0 
0 0 0 1 0 0 0 0 
0 0 0 0 0 0 0 1 
0 0 0 0 1 0 0 0  



Approach: The idea is to use Hill Climbing Algorithm

Algorithm:  

  1. Start with a random state(i.e, a random configuration of the board).
  2. Scan through all possible neighbours of the current state and jump to the neighbour with the highest objective value, if found any. If there does not exist, a neighbour, with objective strictly higher than the current state but there exists one with equal then jump to any random neighbour(escaping shoulder and/or local optimum).
  3. Repeat step 2, until a state whose objective is strictly higher than all it’s neighbour’s objectives, is found and then go to step 4.
  4. The state thus found after the local search is either the local optimum or the global optimum. There is no way of escaping local optima but adding a random neighbour or a random restart each time a local optimum is encountered increases the chances of achieving global optimum(the solution to our problem).
  5. Output the state and return.

Below is the implementation of the Hill-Climbing algorithm:




// C++ implementation of the
// above approach
#include <iostream>
#include <math.h>
 
#define N 8
using namespace std;
 
// A utility function that configures
// the 2D array "board" and
// array "state" randomly to provide
// a starting point for the algorithm.
void configureRandomly(int board[][N],
                       int* state)
{
 
    // Seed for the random function
    srand(time(0));
 
    // Iterating through the
    // column indices
    for (int i = 0; i < N; i++) {
 
        // Getting a random row index
        state[i] = rand() % N;
 
        // Placing a queen on the
        // obtained place in
        // chessboard.
        board[state[i]][i] = 1;
    }
}
 
// A utility function that prints
// the 2D array "board".
void printBoard(int board[][N])
{
 
    for (int i = 0; i < N; i++) {
        cout << " ";
        for (int j = 0; j < N; j++) {
            cout << board[i][j] << " ";
        }
        cout << "\n";
    }
}
 
// A utility function that prints
// the array "state".
void printState(int* state)
{
 
    for (int i = 0; i < N; i++) {
        cout << " " << state[i] << " ";
    }
    cout << endl;
}
 
// A utility function that compares
// two arrays, state1 and state2 and
// returns true if equal
// and false otherwise.
bool compareStates(int* state1,
                   int* state2)
{
 
    for (int i = 0; i < N; i++) {
        if (state1[i] != state2[i]) {
            return false;
        }
    }
    return true;
}
 
// A utility function that fills
// the 2D array "board" with
// values "value"
void fill(int board[][N], int value)
{
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            board[i][j] = value;
        }
    }
}
 
// This function calculates the
// objective value of the
// state(queens attacking each other)
// using the board by the
// following logic.
int calculateObjective(int board[][N],
                       int* state)
{
 
    // For each queen in a column, we check
    // for other queens falling in the line
    // of our current queen and if found,
    // any, then we increment the variable
    // attacking count.
 
    // Number of queens attacking each other,
    // initially zero.
    int attacking = 0;
 
    // Variables to index a particular
    // row and column on board.
    int row, col;
 
    for (int i = 0; i < N; i++) {
 
        // At each column 'i', the queen is
        // placed at row 'state[i]', by the
        // definition of our state.
 
        // To the left of same row
        // (row remains constant
        // and col decreases)
        row = state[i], col = i - 1;
        while (col >= 0
               && board[row][col] != 1) {
            col--;
        }
        if (col >= 0
            && board[row][col] == 1) {
            attacking++;
        }
 
        // To the right of same row
        // (row remains constant
        // and col increases)
        row = state[i], col = i + 1;
        while (col < N
               && board[row][col] != 1) {
            col++;
        }
        if (col < N
            && board[row][col] == 1) {
            attacking++;
        }
 
        // Diagonally to the left up
        // (row and col simultaneously
        // decrease)
        row = state[i] - 1, col = i - 1;
        while (col >= 0 && row >= 0
               && board[row][col] != 1) {
            col--;
            row--;
        }
        if (col >= 0 && row >= 0
            && board[row][col] == 1) {
            attacking++;
        }
 
        // Diagonally to the right down
        // (row and col simultaneously
        // increase)
        row = state[i] + 1, col = i + 1;
        while (col < N && row < N
               && board[row][col] != 1) {
            col++;
            row++;
        }
        if (col < N && row < N
            && board[row][col] == 1) {
            attacking++;
        }
 
        // Diagonally to the left down
        // (col decreases and row
        // increases)
        row = state[i] + 1, col = i - 1;
        while (col >= 0 && row < N
               && board[row][col] != 1) {
            col--;
            row++;
        }
        if (col >= 0 && row < N
            && board[row][col] == 1) {
            attacking++;
        }
 
        // Diagonally to the right up
        // (col increases and row
        // decreases)
        row = state[i] - 1, col = i + 1;
        while (col < N && row >= 0
               && board[row][col] != 1) {
            col++;
            row--;
        }
        if (col < N && row >= 0
            && board[row][col] == 1) {
            attacking++;
        }
    }
 
    // Return pairs.
    return (int)(attacking / 2);
}
 
// A utility function that
// generates a board configuration
// given the state.
void generateBoard(int board[][N],
                   int* state)
{
 
    fill(board, 0);
    for (int i = 0; i < N; i++) {
        board[state[i]][i] = 1;
    }
}
 
// A utility function that copies
// contents of state2 to state1.
void copyState(int* state1, int* state2)
{
 
    for (int i = 0; i < N; i++) {
        state1[i] = state2[i];
    }
}
 
// This function gets the neighbour
// of the current state having
// the least objective value
// amongst all neighbours as
// well as the current state.
void getNeighbour(int board[][N],
                  int* state)
{
    // Declaring and initializing the
    // optimal board and state with
    // the current board and the state
    // as the starting point.
 
    int opBoard[N][N];
    int opState[N];
 
    copyState(opState,
              state);
    generateBoard(opBoard,
                  opState);
 
    // Initializing the optimal
    // objective value
 
    int opObjective
        = calculateObjective(opBoard,
                             opState);
 
    // Declaring and initializing
    // the temporary board and
    // state for the purpose
    // of computation.
 
    int NeighbourBoard[N][N];
    int NeighbourState[N];
 
    copyState(NeighbourState,
              state);
    generateBoard(NeighbourBoard,
                  NeighbourState);
 
    // Iterating through all
    // possible neighbours
    // of the board.
 
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
 
            // Condition for skipping the
            // current state
 
            if (j != state[i]) {
 
                // Initializing temporary
                // neighbour with the
                // current neighbour.
 
                NeighbourState[i] = j;
                NeighbourBoard[NeighbourState[i]][i]
                    = 1;
                NeighbourBoard[state[i]][i]
                    = 0;
 
                // Calculating the objective
                // value of the neighbour.
 
                int temp
                    = calculateObjective(
                        NeighbourBoard,
                        NeighbourState);
 
                // Comparing temporary and optimal
                // neighbour objectives and if
                // temporary is less than optimal
                // then updating accordingly.
 
                if (temp <= opObjective) {
                    opObjective = temp;
                    copyState(opState,
                              NeighbourState);
                    generateBoard(opBoard,
                                  opState);
                }
 
                // Going back to the original
                // configuration for the next
                // iteration.
 
                NeighbourBoard[NeighbourState[i]][i]
                    = 0;
                NeighbourState[i] = state[i];
                NeighbourBoard[state[i]][i] = 1;
            }
        }
    }
 
    // Copying the optimal board and
    // state thus found to the current
    // board and, state since c++ doesn't
    // allow returning multiple values.
 
    copyState(state, opState);
    fill(board, 0);
    generateBoard(board, state);
}
 
void hillClimbing(int board[][N],
                  int* state)
{
 
    // Declaring  and initializing the
    // neighbour board and state with
    // the current board and the state
    // as the starting point.
 
    int neighbourBoard[N][N] = {};
    int neighbourState[N];
 
    copyState(neighbourState, state);
    generateBoard(neighbourBoard,
                  neighbourState);
 
    do {
 
        // Copying the neighbour board and
        // state to the current board and
        // state, since a neighbour
        // becomes current after the jump.
 
        copyState(state, neighbourState);
        generateBoard(board, state);
 
        // Getting the optimal neighbour
 
        getNeighbour(neighbourBoard,
                     neighbourState);
 
        if (compareStates(state,
                          neighbourState)) {
 
            // If neighbour and current are
            // equal then no optimal neighbour
            // exists and therefore output the
            // result and break the loop.
 
            printBoard(board);
            break;
        }
        else if (calculateObjective(board,
                                    state)
                 == calculateObjective(
                        neighbourBoard,
                        neighbourState)) {
 
            // If neighbour and current are
            // not equal but their objectives
            // are equal then we are either
            // approaching a shoulder or a
            // local optimum, in any case,
            // jump to a random neighbour
            // to escape it.
 
            // Random neighbour
            neighbourState[rand() % N]
                = rand() % N;
            generateBoard(neighbourBoard,
                          neighbourState);
        }
 
    } while (true);
}
 
// Driver code
int main()
{
 
    int state[N] = {};
    int board[N][N] = {};
 
    // Getting a starting point by
    // randomly configuring the board
    configureRandomly(board, state);
 
    // Do hill climbing on the
    // board obtained
    hillClimbing(board, state);
 
    return 0;
}




import java.util.Arrays;
import java.util.Random;
 
public class NQueensHillClimbing {
    static final int N = 8;
 
    public static void main(String[] args) {
        int[] state = new int[N];
        int[][] board = new int[N][N];
 
        configureRandomly(board, state);
        hillClimbing(board, state);
    }
 
    static void configureRandomly(int[][] board, int[] state) {
        Random rand = new Random();
 
        for (int i = 0; i < N; i++) {
            state[i] = rand.nextInt(N);
            board[state[i]][i] = 1;
        }
    }
 
    static void printBoard(int[][] board) {
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                System.out.print(" " + board[i][j] + " ");
            }
            System.out.println();
        }
    }
 
    static void printState(int[] state) {
        System.out.println(" " + Arrays.toString(state) + " ");
    }
 
    static boolean compareStates(int[] state1, int[] state2) {
        return Arrays.equals(state1, state2);
    }
 
    static void fill(int[][] board, int value) {
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                board[i][j] = value;
            }
        }
    }
 
    static int calculateObjective(int[][] board, int[] state) {
        int attacking = 0;
 
        for (int i = 0; i < N; i++) {
            int row, col;
            row = state[i];
            col = i - 1;
 
            while (col >= 0 && board[row][col] != 1) {
                col--;
            }
            if (col >= 0 && board[row][col] == 1) {
                attacking++;
            }
 
            row = state[i];
            col = i + 1;
            while (col < N && board[row][col] != 1) {
                col++;
            }
            if (col < N && board[row][col] == 1) {
                attacking++;
            }
 
            row = state[i] - 1;
            col = i - 1;
            while (col >= 0 && row >= 0 && board[row][col] != 1) {
                col--;
                row--;
            }
            if (col >= 0 && row >= 0 && board[row][col] == 1) {
                attacking++;
            }
 
            row = state[i] + 1;
            col = i + 1;
            while (col < N && row < N && board[row][col] != 1) {
                col++;
                row++;
            }
            if (col < N && row < N && board[row][col] == 1) {
                attacking++;
            }
 
            row = state[i] + 1;
            col = i - 1;
            while (col >= 0 && row < N && board[row][col] != 1) {
                col--;
                row++;
            }
            if (col >= 0 && row < N && board[row][col] == 1) {
                attacking++;
            }
 
            row = state[i] - 1;
            col = i + 1;
            while (col < N && row >= 0 && board[row][col] != 1) {
                col++;
                row--;
            }
            if (col < N && row >= 0 && board[row][col] == 1) {
                attacking++;
            }
        }
        return attacking / 2;
    }
 
    static void generateBoard(int[][] board, int[] state) {
        fill(board, 0);
        for (int i = 0; i < N; i++) {
            board[state[i]][i] = 1;
        }
    }
 
    static void copyState(int[] state1, int[] state2) {
        System.arraycopy(state2, 0, state1, 0, N);
    }
 
    static void getNeighbour(int[][] board, int[] state) {
        int[][] opBoard = new int[N][N];
        int[] opState = new int[N];
        copyState(opState, state);
        generateBoard(opBoard, opState);
 
        int opObjective = calculateObjective(opBoard, opState);
 
        int[][] neighbourBoard = new int[N][N];
        int[] neighbourState = new int[N];
        copyState(neighbourState, state);
        generateBoard(neighbourBoard, neighbourState);
 
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (j != state[i]) {
                    neighbourState[i] = j;
                    neighbourBoard[neighbourState[i]][i] = 1;
                    neighbourBoard[state[i]][i] = 0;
 
                    int temp = calculateObjective(neighbourBoard, neighbourState);
 
                    if (temp <= opObjective) {
                        opObjective = temp;
                        copyState(opState, neighbourState);
                        generateBoard(opBoard, opState);
                    }
 
                    neighbourBoard[neighbourState[i]][i] = 0;
                    neighbourState[i] = state[i];
                    neighbourBoard[state[i]][i] = 1;
                }
            }
        }
 
        copyState(state, opState);
        fill(board, 0);
        generateBoard(board, state);
    }
 
    static void hillClimbing(int[][] board, int[] state) {
        int[][] neighbourBoard = new int[N][N];
        int[] neighbourState = new int[N];
        generateBoard(neighbourBoard, neighbourState);
 
        do {
            copyState(state, neighbourState);
            generateBoard(board, state);
            getNeighbour(neighbourBoard, neighbourState);
 
            if (compareStates(state, neighbourState)) {
                printBoard(board);
                break;
            } else if (calculateObjective(board, state) == calculateObjective(neighbourBoard,
                                                                              neighbourState)) {
                neighbourState[(int) (Math.random() * N)] = (int) (Math.random() * N);
                generateBoard(neighbourBoard, neighbourState);
            }
        } while (true);
    }
}




# Python3 implementation of the
# above approach
from random import randint
 
N = 8
 
# A utility function that configures
# the 2D array "board" and
# array "state" randomly to provide
# a starting point for the algorithm.
def configureRandomly(board, state):
 
    # Iterating through the
    # column indices
    for i in range(N):
 
        # Getting a random row index
        state[i] = randint(0, 100000) % N;
 
        # Placing a queen on the
        # obtained place in
        # chessboard.
        board[state[i]][i] = 1;
    
# A utility function that prints
# the 2D array "board".
def printBoard(board):
     
    for i in range(N):
        print(*board[i])
 
# A utility function that prints
# the array "state".
def printState( state):
    print(*state)
     
# A utility function that compares
# two arrays, state1 and state2 and
# returns True if equal
# and False otherwise.
def compareStates(state1, state2):
 
 
    for i in range(N):
        if (state1[i] != state2[i]):
            return False;
     
    return True;
 
# A utility function that fills
# the 2D array "board" with
# values "value"
def fill(board, value):
     
    for i in range(N):
        for j in range(N):
            board[i][j] = value;
         
# This function calculates the
# objective value of the
# state(queens attacking each other)
# using the board by the
# following logic.
def calculateObjective( board, state):
 
    # For each queen in a column, we check
    # for other queens falling in the line
    # of our current queen and if found,
    # any, then we increment the variable
    # attacking count.
 
    # Number of queens attacking each other,
    # initially zero.
    attacking = 0;
 
    # Variables to index a particular
    # row and column on board.
    for i in range(N):
 
        # At each column 'i', the queen is
        # placed at row 'state[i]', by the
        # definition of our state.
 
        # To the left of same row
        # (row remains constant
        # and col decreases)
        row = state[i]
        col = i - 1;
        while (col >= 0 and board[row][col] != 1) :
            col -= 1
         
        if (col >= 0 and board[row][col] == 1) :
            attacking += 1;
         
        # To the right of same row
        # (row remains constant
        # and col increases)
        row = state[i]
        col = i + 1;
        while (col < N and board[row][col] != 1):
            col += 1;
         
        if (col < N and board[row][col] == 1) :
            attacking += 1;
         
        # Diagonally to the left up
        # (row and col simultaneously
        # decrease)
        row = state[i] - 1
        col = i - 1;
        while (col >= 0 and row >= 0 and board[row][col] != 1) :
            col-= 1;
            row-= 1;
         
        if (col >= 0 and row >= 0  and board[row][col] == 1) :
            attacking+= 1;
         
        # Diagonally to the right down
        # (row and col simultaneously
        # increase)
        row = state[i] + 1
        col = i + 1;
        while (col < N and row < N  and board[row][col] != 1) :
            col+= 1;
            row+= 1;
         
        if (col < N and row < N and board[row][col] == 1) :
            attacking += 1;
         
        # Diagonally to the left down
        # (col decreases and row
        # increases)
        row = state[i] + 1
        col = i - 1;
        while (col >= 0 and row < N  and board[row][col] != 1) :
            col -= 1;
            row += 1;
         
        if (col >= 0 and row < N and board[row][col] == 1) :
            attacking += 1;
         
        # Diagonally to the right up
        # (col increases and row
        # decreases)
        row = state[i] - 1
        col = i + 1;
        while (col < N and row >= 0  and board[row][col] != 1) :
            col += 1;
            row -= 1;
         
        if (col < N and row >= 0 and board[row][col] == 1) :
            attacking += 1;
         
    # Return pairs.
    return int(attacking / 2);
 
# A utility function that
# generates a board configuration
# given the state.
def generateBoard( board, state):
    fill(board, 0);
    for i in range(N):
        board[state[i]][i] = 1;
     
# A utility function that copies
# contents of state2 to state1.
def copyState( state1, state2):
 
    for i in range(N):
        state1[i] = state2[i];
     
# This function gets the neighbour
# of the current state having
# the least objective value
# amongst all neighbours as
# well as the current state.
def getNeighbour(board, state):
 
    # Declaring and initializing the
    # optimal board and state with
    # the current board and the state
    # as the starting point.
    opBoard = [[0 for _ in range(N)] for _ in range(N)]
    opState = [0 for _ in range(N)]
 
    copyState(opState, state);
    generateBoard(opBoard, opState);
 
    # Initializing the optimal
    # objective value
    opObjective  = calculateObjective(opBoard, opState);
 
    # Declaring and initializing
    # the temporary board and
    # state for the purpose
    # of computation.
    NeighbourBoard = [[0 for _ in range(N)] for _ in range(N)]
     
    NeighbourState = [0 for _ in range(N)]
    copyState(NeighbourState, state);
    generateBoard(NeighbourBoard, NeighbourState);
 
    # Iterating through all
    # possible neighbours
    # of the board.
    for i in range(N):
        for j in range(N):
 
            # Condition for skipping the
            # current state
            if (j != state[i]) :
 
                # Initializing temporary
                # neighbour with the
                # current neighbour.
                NeighbourState[i] = j;
                NeighbourBoard[NeighbourState[i]][i] = 1;
                NeighbourBoard[state[i]][i] = 0;
 
                # Calculating the objective
                # value of the neighbour.
                temp = calculateObjective( NeighbourBoard, NeighbourState);
 
                # Comparing temporary and optimal
                # neighbour objectives and if
                # temporary is less than optimal
                # then updating accordingly.
 
                if (temp <= opObjective) :
                    opObjective = temp;
                    copyState(opState, NeighbourState);
                    generateBoard(opBoard, opState);
                 
                # Going back to the original
                # configuration for the next
                # iteration.
                NeighbourBoard[NeighbourState[i]][i] = 0;
                NeighbourState[i] = state[i];
                NeighbourBoard[state[i]][i] = 1;
             
    # Copying the optimal board and
    # state thus found to the current
    # board and, state since c+= 1 doesn't
    # allow returning multiple values.
    copyState(state, opState);
    fill(board, 0);
    generateBoard(board, state);
 
def hillClimbing(board, state):
 
    # Declaring  and initializing the
    # neighbour board and state with
    # the current board and the state
    # as the starting point.
 
    neighbourBoard = [[0 for _ in range(N)] for _ in range(N)
    neighbourState = [0 for _ in range(N)]
 
    copyState(neighbourState, state);
    generateBoard(neighbourBoard, neighbourState);
     
    while True:
 
        # Copying the neighbour board and
        # state to the current board and
        # state, since a neighbour
        # becomes current after the jump.
 
        copyState(state, neighbourState);
        generateBoard(board, state);
 
        # Getting the optimal neighbour
 
        getNeighbour(neighbourBoard, neighbourState);
 
        if (compareStates(state, neighbourState)) :
 
            # If neighbour and current are
            # equal then no optimal neighbour
            # exists and therefore output the
            # result and break the loop.
 
            printBoard(board);
            break;
         
        elif (calculateObjective(board, state) == calculateObjective( neighbourBoard,neighbourState)):
 
            # If neighbour and current are
            # not equal but their objectives
            # are equal then we are either
            # approaching a shoulder or a
            # local optimum, in any case,
            # jump to a random neighbour
            # to escape it.
 
            # Random neighbour
            neighbourState[randint(0, 100000) % N]  = randint(0, 100000) % N;
            generateBoard(neighbourBoard, neighbourState);
         
# Driver code
state = [0] * N
board = [[0 for _ in range(N)] for _ in range(N)]
 
# Getting a starting point by
# randomly configuring the board
configureRandomly(board, state);
 
# Do hill climbing on the
# board obtained
hillClimbing(board, state);
 
# This code is contributed by phasing17.




using System;
 
class Program
{
    const int N = 8;
 
    static void ConfigureRandomly(int[,] board, int[] state)
    {
        Random rand = new Random();
 
        for (int i = 0; i < N; i++)
        {
            state[i] = rand.Next(N);
            board[state[i], i] = 1;
        }
    }
 
    static void PrintBoard(int[,] board)
    {
        for (int i = 0; i < N; i++)
        {
            Console.Write(" ");
            for (int j = 0; j < N; j++)
            {
                Console.Write(board[i, j] + " ");
            }
            Console.WriteLine();
        }
    }
 
    static void PrintState(int[] state)
    {
        for (int i = 0; i < N; i++)
        {
            Console.Write(" " + state[i] + " ");
        }
        Console.WriteLine();
    }
 
    static bool CompareStates(int[] state1, int[] state2)
    {
        for (int i = 0; i < N; i++)
        {
            if (state1[i] != state2[i])
            {
                return false;
            }
        }
        return true;
    }
 
    static void Fill(int[,] board, int value)
    {
        for (int i = 0; i < N; i++)
        {
            for (int j = 0; j < N; j++)
            {
                board[i, j] = value;
            }
        }
    }
 
    static int CalculateObjective(int[,] board, int[] state)
    {
        int attacking = 0;
        int row, col;
 
        for (int i = 0; i < N; i++)
        {
            row = state[i];
            col = i - 1;
            while (col >= 0 && board[row, col] != 1)
            {
                col--;
            }
            if (col >= 0 && board[row, col] == 1)
            {
                attacking++;
            }
 
            row = state[i];
            col = i + 1;
            while (col < N && board[row, col] != 1)
            {
                col++;
            }
            if (col < N && board[row, col] == 1)
            {
                attacking++;
            }
 
            row = state[i] - 1;
            col = i - 1;
            while (col >= 0 && row >= 0 && board[row, col] != 1)
            {
                col--;
                row--;
            }
            if (col >= 0 && row >= 0 && board[row, col] == 1)
            {
                attacking++;
            }
 
            row = state[i] + 1;
            col = i + 1;
            while (col < N && row < N && board[row, col] != 1)
            {
                col++;
                row++;
            }
            if (col < N && row < N && board[row, col] == 1)
            {
                attacking++;
            }
 
            row = state[i] + 1;
            col = i - 1;
            while (col >= 0 && row < N && board[row, col] != 1)
            {
                col--;
                row++;
            }
            if (col >= 0 && row < N && board[row, col] == 1)
            {
                attacking++;
            }
 
            row = state[i] - 1;
            col = i + 1;
            while (col < N && row >= 0 && board[row, col] != 1)
            {
                col++;
                row--;
            }
            if (col < N && row >= 0 && board[row, col] == 1)
            {
                attacking++;
            }
        }
 
        return attacking / 2;
    }
 
    static void GenerateBoard(int[,] board, int[] state)
    {
        Fill(board, 0);
        for (int i = 0; i < N; i++)
        {
            board[state[i], i] = 1;
        }
    }
 
    static void CopyState(int[] state1, int[] state2)
    {
        Array.Copy(state2, state1, N);
    }
 
    static void GetNeighbour(int[,] board, int[] state)
    {
        int[,] opBoard = new int[N, N];
        int[] opState = new int[N];
        CopyState(opState, state);
        GenerateBoard(opBoard, opState);
        int opObjective = CalculateObjective(opBoard, opState);
 
        int[,] neighbourBoard = new int[N, N];
        int[] neighbourState = new int[N];
        CopyState(neighbourState, state);
        GenerateBoard(neighbourBoard, neighbourState);
 
        for (int i = 0; i < N; i++)
        {
            for (int j = 0; j < N; j++)
            {
                if (j != state[i])
                {
                    neighbourState[i] = j;
                    neighbourBoard[neighbourState[i], i] = 1;
                    neighbourBoard[state[i], i] = 0;
                    int temp = CalculateObjective(neighbourBoard, neighbourState);
 
                    if (temp <= opObjective)
                    {
                        opObjective = temp;
                        CopyState(opState, neighbourState);
                        GenerateBoard(opBoard, opState);
                    }
 
                    neighbourBoard[neighbourState[i], i] = 0;
                    neighbourState[i] = state[i];
                    neighbourBoard[state[i], i] = 1;
                }
            }
        }
 
        CopyState(state, opState);
        Fill(board, 0);
        GenerateBoard(board, state);
    }
 
    static void HillClimbing(int[,] board, int[] state)
    {
        int[,] neighbourBoard = new int[N, N];
        int[] neighbourState = new int[N];
 
        CopyState(neighbourState, state);
        GenerateBoard(neighbourBoard, neighbourState);
 
        do
        {
            CopyState(state, neighbourState);
            GenerateBoard(board, state);
            GetNeighbour(neighbourBoard, neighbourState);
 
            if (CompareStates(state, neighbourState))
            {
                PrintBoard(board);
                break;
            }
            else if (CalculateObjective(board, state) == CalculateObjective(neighbourBoard, neighbourState))
            {
                neighbourState[new Random().Next(N)] = new Random().Next(N);
                GenerateBoard(neighbourBoard, neighbourState);
            }
 
        } while (true);
    }
 
    static void Main(string[] args)
    {
        int[] state = new int[N];
        int[,] board = new int[N, N];
 
        ConfigureRandomly(board, state);
        HillClimbing(board, state);
    }
}




// JS implementation of the
// above approach
let  N = 8
 
// A utility function that configures
// the 2D array "board" and
// array "state" randomly to provide
// a starting point for the algorithm.
function configureRandomly(board, state)
{
 
    // Iterating through the
    // column indices
    for (var i = 0; i < N; i++) {
 
        // Getting a random row index
        state[i] = Math.floor(Math.random() * 100000) % N;
 
        // Placing a queen on the
        // obtained place in
        // chessboard.
        board[state[i]][i] = 1;
    }
}
 
// A utility function that prints
// the 2D array "board".
function printBoard(board)
{
 
    for (var i = 0; i < N; i++) {
        process.stdout.write(" ");
        for (var j = 0; j < N; j++) {
            process.stdout.write(board[i][j] + " ");
        }
        process.stdout.write("\n");
    }
}
 
// A utility function that prints
// the array "state".
function printState( state)
{
 
    for (var i = 0; i < N; i++) {
       process.stdout.write(" " + state[i] + " ");
    }
    process.stdout.write("\n");
}
 
// A utility function that compares
// two arrays, state1 and state2 and
// returns true if equal
// and false otherwise.
function compareStates(state1,
                   state2)
{
 
    for (var i = 0; i < N; i++) {
        if (state1[i] != state2[i]) {
            return false;
        }
    }
    return true;
}
 
// A utility function that fills
// the 2D array "board" with
// values "value"
function fill(board, value)
{
    for (var i = 0; i < N; i++) {
        for (var j = 0; j < N; j++) {
            board[i][j] = value;
        }
    }
}
 
// This function calculates the
// objective value of the
// state(queens attacking each other)
// using the board by the
// following logic.
function calculateObjective( board,
                        state)
{
 
    // For each queen in a column, we check
    // for other queens falling in the line
    // of our current queen and if found,
    // any, then we increment the variable
    // attacking count.
 
    // Number of queens attacking each other,
    // initially zero.
    var attacking = 0;
 
    // Variables to index a particular
    // row and column on board.
    var row, col;
 
    for (var i = 0; i < N; i++) {
 
        // At each column 'i', the queen is
        // placed at row 'state[i]', by the
        // definition of our state.
 
        // To the left of same row
        // (row remains constant
        // and col decreases)
        row = state[i], col = i - 1;
        while (col >= 0
               && board[row][col] != 1) {
            col--;
        }
        if (col >= 0
            && board[row][col] == 1) {
            attacking++;
        }
 
        // To the right of same row
        // (row remains constant
        // and col increases)
        row = state[i], col = i + 1;
        while (col < N
               && board[row][col] != 1) {
            col++;
        }
        if (col < N
            && board[row][col] == 1) {
            attacking++;
        }
 
        // Diagonally to the left up
        // (row and col simultaneously
        // decrease)
        row = state[i] - 1, col = i - 1;
        while (col >= 0 && row >= 0
               && board[row][col] != 1) {
            col--;
            row--;
        }
        if (col >= 0 && row >= 0
            && board[row][col] == 1) {
            attacking++;
        }
 
        // Diagonally to the right down
        // (row and col simultaneously
        // increase)
        row = state[i] + 1, col = i + 1;
        while (col < N && row < N
               && board[row][col] != 1) {
            col++;
            row++;
        }
        if (col < N && row < N
            && board[row][col] == 1) {
            attacking++;
        }
 
        // Diagonally to the left down
        // (col decreases and row
        // increases)
        row = state[i] + 1, col = i - 1;
        while (col >= 0 && row < N
               && board[row][col] != 1) {
            col--;
            row++;
        }
        if (col >= 0 && row < N
            && board[row][col] == 1) {
            attacking++;
        }
 
        // Diagonally to the right up
        // (col increases and row
        // decreases)
        row = state[i] - 1, col = i + 1;
        while (col < N && row >= 0
               && board[row][col] != 1) {
            col++;
            row--;
        }
        if (col < N && row >= 0
            && board[row][col] == 1) {
            attacking++;
        }
    }
 
    // Return pairs.
    return Math.floor(attacking / 2);
}
 
// A utility function that
// generates a board configuration
// given the state.
function generateBoard( board,
                   state)
{
 
    fill(board, 0);
    for (var i = 0; i < N; i++) {
        board[state[i]][i] = 1;
    }
}
 
// A utility function that copies
// contents of state2 to state1.
function copyState( state1, state2)
{
 
    for (var i = 0; i < N; i++) {
        state1[i] = state2[i];
    }
}
 
// This function gets the neighbour
// of the current state having
// the least objective value
// amongst all neighbours as
// well as the current state.
function getNeighbour(board,
                  state)
{
    // Declaring and initializing the
    // optimal board and state with
    // the current board and the state
    // as the starting point.
 
    var opBoard = new Array(N);
    for (var i = 0; i < N; i++)
        opBoard[i] = new Array(N).fill(0);
    var opState = new Array(N).fill(0);
 
    copyState(opState,
              state);
    generateBoard(opBoard,
                  opState);
 
    // Initializing the optimal
    // objective value
 
    var opObjective  = calculateObjective(opBoard,
                             opState);
 
    // Declaring and initializing
    // the temporary board and
    // state for the purpose
    // of computation.
 
    var NeighbourBoard = new Array(N).fill(new Array(N).fill(0));
    var NeighbourState = new Array(N).fill(0);
    copyState(NeighbourState,
              state);
    generateBoard(NeighbourBoard,
                  NeighbourState);
 
    // Iterating through all
    // possible neighbours
    // of the board.
 
    for (var i = 0; i < N; i++) {
        for (var j = 0; j < N; j++) {
 
            // Condition for skipping the
            // current state
 
            if (j != state[i]) {
 
                // Initializing temporary
                // neighbour with the
                // current neighbour.
 
                NeighbourState[i] = j;
                NeighbourBoard[NeighbourState[i]][i]
                    = 1;
                NeighbourBoard[state[i]][i]
                    = 0;
 
                // Calculating the objective
                // value of the neighbour.
 
                var temp
                    = calculateObjective(
                        NeighbourBoard,
                        NeighbourState);
 
                // Comparing temporary and optimal
                // neighbour objectives and if
                // temporary is less than optimal
                // then updating accordingly.
 
                if (temp <= opObjective) {
                    opObjective = temp;
                    copyState(opState,
                              NeighbourState);
                    generateBoard(opBoard,
                                  opState);
                }
 
                // Going back to the original
                // configuration for the next
                // iteration.
 
                NeighbourBoard[NeighbourState[i]][i]
                    = 0;
                NeighbourState[i] = state[i];
                NeighbourBoard[state[i]][i] = 1;
            }
        }
    }
 
    // Copying the optimal board and
    // state thus found to the current
    // board and, state since c++ doesn't
    // allow returning multiple values.
 
    copyState(state, opState);
    fill(board, 0);
    generateBoard(board, state);
}
 
function hillClimbing(board, state)
{
 
    // Declaring  and initializing the
    // neighbour board and state with
    // the current board and the state
    // as the starting point.
 
    var neighbourBoard = new Array(N);
    for (var i = 0; i < N; i++)
        neighbourBoard[i] = new Array(N).fill(0);
    var neighbourState = new Array(N).fill(0)
 
    copyState(neighbourState, state);
    generateBoard(neighbourBoard,
                  neighbourState);
 
    do {
 
        // Copying the neighbour board and
        // state to the current board and
        // state, since a neighbour
        // becomes current after the jump.
 
        copyState(state, neighbourState);
        generateBoard(board, state);
 
        // Getting the optimal neighbour
 
        getNeighbour(neighbourBoard,
                     neighbourState);
 
        if (compareStates(state,
                          neighbourState)) {
 
            // If neighbour and current are
            // equal then no optimal neighbour
            // exists and therefore output the
            // result and break the loop.
 
            printBoard(board);
            break;
        }
        else if (calculateObjective(board,
                                    state)
                 == calculateObjective(
                        neighbourBoard,
                        neighbourState)) {
 
            // If neighbour and current are
            // not equal but their objectives
            // are equal then we are either
            // approaching a shoulder or a
            // local optimum, in any case,
            // jump to a random neighbour
            // to escape it.
 
            // Random neighbour
            neighbourState[(Math.floor(Math.random() * 100000) % N)]
                = Math.floor(Math.random() * 100000) % N;
            generateBoard(neighbourBoard,
                          neighbourState);
        }
 
    } while (true);
}
 
// Driver code
var state = new Array(N).fill(0);
var board =  new Array(N);
for (var i = 0; i < N; i++)
        board[i] = new Array(N).fill(0);
 
    // Getting a starting point by
    // randomly configuring the board
    configureRandomly(board, state);
 
    // Do hill climbing on the
    // board obtained
    hillClimbing(board, state);
 
// This code is contributed by phasing17.

Output
 0 0 1 0 0 0 0 0 
 0 0 0 0 0 1 0 0 
 0 0 0 0 0 0 0 1 
 1 0 0 0 0 0 0 0 
 0 0 0 1 0 0 0 0 
 0 0 0 0 0 0 1 0 
 0 0 0 0 1 0 0 0 
 0 1 0 0 0 0 0 0


Complexity Analysis 
 


Article Tags :