N Queen's question
tags (space delimited): Oj_ algorithm
1. Overview of issues
The N Queen question is a classic question, placing n queens on a n*n board, one for each line and making it impossible to attack each other (the Queen on the same line, the same column, and the same slash will automatically attack).
Solving the N-Queen problem is a classic case of backtracking in algorithms:
?? The backtracking algorithm is also called Heuristic, which is a method to search the solution of the problem systematically. The basic idea of backtracking algorithm is: Go forward from a road, can enter into, can not enter the back, change a road and try again.
在现实中,有很多问题往往需要我们把其所有可能穷举出来,然后从中找出满足某种要求的可能或最优的情况,从而得到整个问题的解。回溯算法就是解决这种问题的“通用算法”,有“万能算法”之称。N皇后问题在N增大时就是这样一个解空间很大的问题,所以比较适合用这种方法求解。这也是N皇后问题的传统解法,很经典。
2. Problem analysis
The following is a high-level pseudo-code description of the algorithm, where a n*n matrix is used to store the board:
1. 算法开始, 清空棋盘,当前行设为第一行,当前列设为第一列2. 在当前行,当前列的位置上判断是否满足条件(即保证经过这一点的行,列与斜线上都没有两个皇后),若不满足,跳到第4步3. 在当前位置上满足条件的情形: - 在当前位置放一个皇后,若当前行是最后一行,记录一个解; - 若当前行不是最后一行,当前行设为下一行, 当前列设为当前行的第一个待测位置; - 若当前行是最后一行,当前列不是最后一列,当前列设为下一列; - 若当前行是最后一行,当前列是最后一列,回溯,即清空当前行及以下各行的棋盘,然后,当前行设为上一行,当前列设为当前行的下一个待测位置; - 以上返回到第2步4. 在当前位置上不满足条件的情形: - 若当前列不是最后一列,当前列设为下一列,返回到第2步; - 若当前列是最后一列了,回溯,即,若当前行已经是第一行了,算法退出,否则,清空当前行及以下各行的棋盘,然后,当前行设为上一行,当前列设为当前行的下一个待测位置,返回到第2步;
?? The basic principle of the algorithm is the above, but the different data structure is different, and the method to check whether a location satisfies the condition is different. In order to improve efficiency, there are various optimization strategies, such as multi-threading, multi-allocation memory representation chessboard, etc.
?? When you specifically resolve the problem, you can split it into several minor issues. First of all, how to determine whether the two queens can attack each other, in the initial contact with this problem, the first thought is to store the chessboard as a two-dimensional array, and then in the first row of the column I to place the Queen, according to the description of the problem, the first judge is whether there is a queen in line I, because there is only one This judgment can also be omitted, and then determine whether the column J has a queen, this is also very simple, the final need to determine whether there is a queen on the same slash, according to the method needs to judge two times, the diagonal direction and the negative diagonal direction, overall is not difficult. But after writing, always feel very stupid, because in the N Queen problem this function is used too many times, and this is inefficient, personal feeling very uncomfortable. Surfing the internet to see someone else's implementation. It was a surprise that Daniel was using a one-dimensional array to store the chessboard, and it was easy to judge whether a queen could attack each other in one place. Specific details are as follows:
?? Save the chessboard as an N-dimensional array a[n], the value of element I in the array represents the empress position of line I, so that the space size of the problem can be compressed into one-dimensional O (N), in judging whether conflict is also very simple, first each row only a queen, and in the array occupies only one element position, the row conflict does not exist Next is the column conflict, judging whether there is a[i] and the current column J to place the Queen is equal. As for the slash conflict, it can be observed that all the queens that clash on the slash have a regular position, i.e. the absolute value of the reciprocal reduction of their ranks is equal, i.e. | Row–i | = | Col–a[i] |. The question of whether a location can be placed on the Queen has been resolved.
Reference documents:
3 Algorithm Implementation 3.1 recursive method
Recursive method is relatively simple, the general idea is as follows:
void queen(intif (n == row) //如果已经找到结果,则打印结果 else { for (k=0 to N) //试探第row行每一个列 if (can_place(row, k) { place(row, k); //放置皇后 1); //继续探测下一行 } } }}
The method because after the detection of line I, if found a can place the Queen's position J, then will be recursive detection of the next line, the end will continue to probe I row j+1 column, so you can find all the N Queen's solution. However, the recursive method is generally less efficient.
The code is implemented as follows
/***************************file:queen.h#ifndef Queen_h#define QUEEN_H***************************//******************************Input parameters: int N: Queen's number return value: int: Number of N Queen scenarios*****************************/int placequeenmethodnum (int n);#endif//! Queen_h
/****************************file:queen.cppauther:spfdata:2015.12.24****************************/#include"Queen.h"#include <cmath>StaticBOOL Checkqueen (intQueen[],intRowintCOL);Static voidPlacequeen (intQueen[],intRowintN_queens,int&result_count);intPlacequeenmethodnum (intN) {int*queen =New int[n];intResult_count =0; Placequeen (Queen,0, n, Result_count); Delete[]queen;returnResult_count;} BOOL Checkqueen (intQueen[],intRowintCol) { for(inti =0; i < row; i++)//And 0~row-1 to place the Queen contrast{if(Queen[i] = = Col | | abs (I-ROW) = = ABS (Queen[i]-col))//Determine if the Queen of line I is in Col column or (Row,col) with (I,queen[i]) whether a slash is common return false; }return true;}voidPlacequeen (intQueen[],intRowintN_queens,int&result_count) {if(row = = N_queens) result_count++;Else{ for(intI_cols =0; I_cols < N_queens; i_cols++)//test the first row{if(Checkqueen (Queen,row, I_cols)) {Queen[row] = I_cols; Placequeen (Queen, Row +1, N_queens,result_count); } } }}
Main
#include<cstdlib>#include<iostream>#include"queen.h"usingnamespacestd;int main(void){ int n; do { cin >> n; cout"个queens的解个数为:" << PlaceQueenMethodNum(n) << endl; while (n); system("pause"); return0;}
Output:
n Solution (N)
1 1
2 0
3 0
4 2
5 10
6 4
7 40
8 92
9 352
10 724
11 2680
12 14200
13 73712
14 365596
15 2279184
16 14772512
17 95815104
18 666090624
19 4968057848
20 39029188884
21 314666222712
22 2691008701644
23 24233937684440
24 227514171973736
25 2207893435808352
3.2 Non-recursive method
?? The question of when and how to backtrack when an important problem of non-recursive method. The program first probes each row in the N row, looking for a place where the queen can be placed, by probing each column of the row to see if the Queen can be placed, or, if possible, placing a queen in the column and then continuing to probe the next line of the Queen's position. If you have already probed all the columns and have not found the column that can place the queen, you should backtrack, move the previous row of the Queen's position back one column, if the previous row queen moved and cannot find the location, then continue backtracking until a row to find the Queen's position or go back to the first line, If the first row of Queens cannot find a place to place the queen, it means that all of the solutions have been found to be terminated. If the row is already the last line, after the row is probed, if the location of the Queen is found, a result is found and printed. But at this point it is no longer possible to end the program here, because we are looking for all the solutions of the N queen problem, and we should clear the Queen of the line and continue probing from the next column where the number of Queens is currently placed.
Code Implementation
* Backtracking method to solve the problem of n Queens
* Use a one-dimensional array to represent the Queen's position
* The subscript of the array indicates the row where the Queen is located
* The value of the array element represents the column where the Queen is located
* This design of the board, all the queen must not be the same line, so the conflict does not exist
/***************************file:queen.h#ifndef Queen_h#define QUEEN_H***************************//******************************Input parameters: int N: Queen's number return value: int: Number of N Queen scenarios*****************************/int placequeenmethodnum (int n);#endif//! Queen_h
/****************************file:queen.cppauther:spfdata:2015.12.24****************************/#include"Queen.h"#include <cmath>StaticBOOL Checkqueen (intQueen[],intRowintCOL);intPlacequeenmethodnum (intN) {int*queen =New int[n];intResult_count =0;introw =0;intCol =0; while(Row < N) { while(col<n)//For the first row, each test, determine its number of columns{if(Checkqueen (Queen, Row, col)) {Queen[row] = col;//Determine the number of columns and start the next line if(Row = = N-1)//Find a solution{result_count++; Break; }Else{row++;//Continue to determine the next line of Queen's position, start searching from column No. 0Col =-1; }} col++; }if(Row = =0)// back to completion Break; row--;//Backtrack, move the Queen's position back one columnCol = queen[row]+1; } Delete[]queen;returnResult_count;}/ * Check the validity of the queen * *BOOL Checkqueen (intQueen[],intRowintCol) { for(inti =0; i < row; i++)//And 0~row-1 to place the Queen contrast{if(Queen[i] = = Col | | abs (I-ROW) = = ABS (Queen[i]-col))//Determine if the Queen of line I is in Col column or (Row,col) with (I,queen[i]) whether a slash is common return false; }return true;}
Main
#include <cstdlib> #include <iostream> #include "Queen.h" using namespace STD ; int Main (void ) { int N; do {cin >> N; cout << n << "queens" the number of solutions is: " < < Placequeenmethodnum (n) << Endl; } while (n); System ( "pause" ); return 0 ;}
- http://blog.csdn.net/hackbuteer1/article/details/6657109
- Http://blog.chinaunix.net/uid-23781137-id-2181724.html
N Queen's question