The backtracking algorithm of n queen problem can be improved by space and time trade-off further. The consideration of positions occupancy is attained by duplicate_array and two integrals. Note that these utilities can not tell all illegal moves because it is performing its job on the basis of chess_board definition. That is, power of utilities contained by chess_board are not enough to telling all illegal moves. It needs a data structure to record positions occupied by chesses. Naturally, it needs three arrays to recording row, column, diagonal1 ( upper left to lower right) and diagonal2 (upper right to lower left). Column is already represented by duplicate_array. So it needs two other array to represent diagonal1,2. Consequently, the job is how to express the meaning of one diagonal is occupied . That is, for a mo # to assign value to the corresponding element in diagonal1, 2. Assuming the one of occupied diagonal1 is diagonal1 [x] and diagonal2 is diagonal2 [y], the ass Ign Diagonal1 [x] and Diagonal2 [Y] to 1 to Denoting these Diagonals Are Occupied. An N Queen Problem HAS 2N-1 Diagonal1s and 2N-1 DiagonAl2s.
The Rules Are: (These Rules Are Obtained by Observation, IT IS CORRECT INTUIVELY (Remind The InTuitionism In Mathematics).).
Diagonal1 [J-CUR_I] = 1 IF J> = CUR_I
Diagonal1 [J-CUR_I 2 * N-1] = 1 IF J
Diagonal2 [J Cur_i] = 1
The Codes:
#include
#include
#include
#include
#include
#include
Using namespace std;
Template
Struct Output_functor: public unary_function
{
Output_functor (): n (0) {}
Void Operator () (const t & p) {
COUT << "(" << n << "," << p << ")" << ""
N ;
}
Int n;
}
Class Chess_Board
{
Vector
Vector
Vector
PUBLIC:
Int n;
INT CUR_I;
INT NUMBER_SOLUTION;
Chess_board (int Dim): N (DIM), CUR_I (0), NUMBER_SOLUTION (0)
{
Array.resize (n, -30000);
Duplicate_Array.resize (n, 0);
Diagonal1.resize (2 * n-1, 0);
Diagonal2.resize (2 * n-1, 0);
}
Void Move (Int J)
{
Array [CUR_I] = J;
IF (j> = cur_i)
{
Diagonal1 [J-CUR_I] = 1;
}
Else
{
Diagonal1 [J-CUR_I 2 * N-1] = 1;
}
Diagonal2 [J CUR_I] = 1;
Duplicate_Array [J] = 1;
}
Void UN_MOVE (INT J)
{
Array [CUR_I] = - 30000;
IF (j> = cur_i)
{
Diagonal1 [J-CUR_I] = 0;
}
Else
{
Diagonal1 [J-CUR_I 2 * N-1] = 0;
}
Diagonal2 [J Cur_i] = 0;
Duplicate_Array [J] = 0;
}
Bool Legal_POS (INT J)
{
IF (duplicate_Array [J] == 0 && Diagonal2 [J Cur_i] == 0)
{
IF (j
{
IF (Diagonal1 [J-Cur_i 2 * N-1] == 0)
Return True;
}
Else
{
IF (Diagonal1 [J-Cur_i] == 0)
Return True;
}
Return False; // tricky. If LACK THIS
}
Else
Return False;
}
Void write ()
{
NUMBER_SOLUTION ;
FOR_EACH (Array.begin (), Array.end (), Output_functor
Cout << Endl;
}
}
Void BackTracking (Chess_Board_delegation & C)
{
IF (c.get_cur_i () == C.GET_N ())
{
c.write ();
C.SET_CUR_I (C.GET_CUR_I () - 1);
Return;
}
Else
{
For (int J = 0; j
{
IF (c.legal_pos (j) == false)
CONTINUE;
C.Move (j);
C.SET_CUR_I (C.GET_CUR_I () 1); BackTracking (C);
C.un_move (j);
}
C.SET_CUR_I (C.GET_CUR_I () - 1);
}
}
OMITTED CHESS_BOARD_DELEGATION and Main
For The Convenient of Test, IT Should Use a Template Argument To Indicate With or WithOut Output.
Template
Class Chess_Board
{
......
Void write ()
{
IF (with_output == true)
{
NUMBER_SOLUTION ;
FOR_EACH (Array.begin (), Array.end (), Output_functor
Cout << Endl;
}
Else
{
NUMBER_SOLUTION ;
}
}
......
}
Template
Class Chess_Board_Delegation
{
Chess_Board
PUBLIC:
Chess_Board_delegation (Chess_Board
......
}
Template
Void BackTracking (Chess_Board_delegation
{
......
}
int main ()
{
......
Chess_board
Chess_board_delegation
......
}
Using specialization can avoid the equality comparison in write function in order to improve the performance a bit The codes of definition of chess_board is: template