八皇后递归求解问题

这篇博客详细介绍了如何使用递归解决八皇后问题,包括确保皇后不在同一行、列和斜线上的策略,以及递归实现的步骤。博主通过设置标记数组和递归调用来找出所有可能的解决方案,并给出了完整的C语言代码示例。
摘要由CSDN通过智能技术生成

昨天在同济医学院参加DeNA宣讲及笔试,最后一题为八皇后递归求解填空,不懂。

今天在上网搜索并认真思考后,在此做一个总结。


求解思路:

棋盘为8行8列,从第0行开始放第一个皇后,设放在第 i 列,接下来,

逐个放其余7行,这个前提保证所有皇后均不在同一行。


还需保证所有皇后不在同一列,这需要用到数组 col[i],0 <= i <= 7,初始化为0,表示没有任何一列放了皇后。

因为我们已在第 0 行的第 i 列放了皇后,我们添加标记 col[i] = 1,表示放其余7行时,第 i 列不能再放皇后。


同时,所有皇后不能在同一斜线上,分两种,斜率为 1 和  -1。如下图所示:

斜率为 1(positive diagonal,正斜线) 即蓝色斜线,这条斜线上的所有方格,行号和列号的和相同;

斜率为 -1(negative diagonal,负斜线) 即绿色斜线,这条斜线上的所有方格,行号和列号的差相同。

为了表示上述两种情况,用数组pd[15],nd[15]表示。

// 因为 row+col 最大为14,同时 row-col 存在 -7 的情况,实际处理时,用 row- col+7,最大也为14

// 所以数组大小均定为 15

因为我们已在第 0 行的第 i 列放了皇后,我们还需添加标记:pd[ 0+i ] = 1,nd[ 0-i+7 ] = 1。


递归实现:

由EightQueen( row = 0 )开始,表示放第0行。

递归终止条件1:当 row == 8 时,得到一个解 count++ ; return;   // 解的数目加1


放每一行时,起初均有8列可放,即for( int i=0; i < 8; i++ ),但需排除被标记的列。

如果某一列被标记,那么该列不可放,需跳过这列continue。(递归终止条件2:所有列均被标记,本轮尝试失败)


选好所放的列后,作标记 col[ i ] = pd[ row+i ] = nd[ row-i+7 ] = 1,然后递归放下一行EightQueen( row+1 )。

当第 row+1 行的递归退出后,第 row 行将换下一列尝试,尝试之前,需将先前本行尝试的列的标记清除,即:

col[ i ] = pd[ row+i ] = nd[ row-i+7 ] = 0。


代码:

#include<stdio.h>

int col[8], pd[15], nd[15], count;

void init()
{
    int i;
    count = 0;
    for( i=0; i<8; i++) col[i] = 0;
    for( i=0; i<15; i++) pd[i] = nd[i] = 0;
}

void EightQueen( int row ) {
    if( row>=8 ) { count++; return; }
    int i;
    for( i=0; i<8; i++ ) {
        if( col[i] || pd[row+i] || nd[row-i+7] ) continue;
        col[i] = pd[row+i] = nd[row-i+7]=1;
        EightQueen( row+1 );
        col[i] = pd[row+i] = nd[row-i+7]=0;
    }
}

int main() {
    init();
    EightQueen( 0 );
    printf("八皇后解的数目为:%d\n",count);
    return 0;
}




  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值