八皇后问题

引入:


皇后是国际象棋威力最大的棋子,可以攻击上下左右和斜方向一共八个方向,我们尝试在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;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值