引入:
皇后是国际象棋威力最大的棋子,可以攻击上下左右和斜方向一共八个方向,我们尝试在8×8的棋盘上摆放八个皇后,试着找出所有的解法(不考虑对称相等)
思考:
可以采用会溯法,先把皇后摆在某行的第一列上,然后检查它是否和棋盘上的其他皇后互相攻击。若是存在相互攻击,将皇后移动到该行的下一列去检查。如果每一列都存在相互攻击的情况,函数就应该返回失败。
但是,如果皇后能够摆放在这个位置上,函数应该继续递归调用自身,把一个皇后放在下一行。当递归调用返回失败时,函数再把原先那个皇后移动到下一列。当一个皇后成功放置于最后一列时,我们就完成了目标,打印棋盘就可以显示八个皇后的位置了。
注意下,在摆放第i个皇后时,此时棋盘已经成功摆放了1~(i-1)个皇后,在第i行摆放时,只要检查上方(up)和斜上方一共三个方向是否有冲突即可。
实现一下:
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#define N 8
bool matrix[ N+1 ][ N+1 ] = { 0 };
using namespace std;
bool IsLegal( const int &i, const int &j );
void print_matrix( void );
void place_queen( int row );
int main( int argc, char *args[] )
{
bool matrix[ N+1 ][ N+1 ] = { 0 };
place_queen( 1 );
return EXIT_SUCCESS;
}
bool IsLegal( const int &i, const int &j )
{
/*
* judge whether the placed i-1 queen is legal with our current matrix[ i ][ j ] , i == 1 is legal
* return true means ok there is no conflict
* return false means there is conflict
*/
for( int m = 1; m <= i - 1; ++m ){
for( int n = 1; n <= N; ++n ){
if( matrix[ m ][ n ] == 1 )
if( n == j || abs( i - m ) == abs( j - n ) ) // conflict has detected
return false; // n==j means up direction, abs(m-i) and abs(n-j) means oblique direction
}
}
return true;
}
void print_matrix( void )
{
static int count = 1;
printf("Case : %d \n", count++ );
for( int i = 1; i <= N; ++i ){
for( int j = 1; j <= N; ++j ){
matrix[ i ][ j ] == 1 ? printf("%c ", 'Q') : printf(". ");
}
cout << endl;
}
cout << endl;
}
void place_queen( int row )
{
/*
* we assume that the board N*N has placed (row-1) queen
* now we should find a position at the row line
*/
if( row > N )
print_matrix( ); // print the board
for( int column = 1; column <= N; ++column ){
matrix[ row ][ column ] = 1; // make a tag for each procedure, recurse knows what the placed queen is
if( IsLegal( row, column ) ) // if the current position is correct, place the next row
place_queen( row + 1 );
matrix[ row ][ column ] = 0;
}
}