关于八皇后问题的C语言解法

八皇后问题由高斯(C. F. Gauss)最早在1850年提出并研究,但并未完全解决。N皇后问题指在一个N×N的棋盘上放置N个皇后,使任意两个皇后都不能互相攻击。按国际象棋规则,两个皇后,若在同一行上,或在同一列上, 或在同一条斜线上, 则她们可以互相攻击。下图即满足八皇后条件的一种棋局。

编写程序给出所有摆法和满足条件的棋局数目。

Exp08-Basic02.jpg

代码思路:

1.找出对角线(包括主,副对角线)之间的规律关系。

2.了解 回溯法的使用(递归)如果你不会,那么看完博客你大概也就懂了。

八皇后问题是使用回溯法解决的典型案例。算法的解决思路是:

1. 从棋盘的第一行开始,从第一个位置开始,依次判断当前位置是否能够放置皇后,判断的依据为:同该行之前的所有行中皇后的所在位置进行比较,如果在同一列,或者在同一条斜线上(斜线有两条,为正方形的两个对角线),都不符合要求,继续检验后序的位置。

2. 如果该行所有位置都不符合要求,则回溯到前一行,改变皇后的位置,继续试探。

3. 如果试探到最后一行,所有皇后摆放完毕,则直接打印出 8*8 的棋盘。最后一定要记得将棋盘恢复原样,避免影响下一次摆放。

代码如下(看着多,其实大部分是注释占行,其实很简洁明了):

#include <stdio.h>
int Queenes[8]={0},Counts=0;//queen是一个列坐标; 
int Check(int line,int list){
    //遍历该行之前的所有行
    for (int index=0; index<line; index++) {
        //挨个取出前面行中皇后所在位置的列坐标
        int data=Queenes[index];
        //如果在同一列,该位置不能放
        if (list==data) {
            return 0;
        }
        //如果当前位置的斜上方有皇后,在一条斜线上,也不行
        if ((index+data)==(line+list)) {
            return 0;
        }
        //如果当前位置的斜下方有皇后,在一条斜线上,也不行
        if ((index-data)==(line-list)) {
            return 0;
        }
    }
    //如果以上情况都不是,当前位置就可以放皇后
    return 1;
}
//输出语句
void print()
{
    for (int line = 0; line < 8; line++)
    {
        int list;
        for (list = 0; list < Queenes[line]; list++)
            printf("0");
        printf("#");
        for (list = Queenes[line] + 1; list < 8; list++){
            printf("0");
        }
        printf("\n");
    }
    printf("================\n");
}
void eight_queen(int line){
    //在数组中为0-7列
    for (int list=0; list<8; list++) {
        //对于固定的行列,检查是否和之前的皇后位置冲突
        if (Check(line, list)) {
            //不冲突,以行为下标的数组位置记录列数
            Queenes[line]=list;
            //如果最后一样也不冲突,证明为一个正确的摆法
            if (line==7) {
                //统计摆法的Counts加1
                Counts++;
                //输出这个摆法
                print();//因为是void型函数 
                //每次成功,都要将数组重归为0
                Queenes[line]=0;
                return;
            }
            //继续判断下一样皇后的摆法,递归
            eight_queen(line+1);
            //不管成功失败,该位置都要重新归0,以便重复使用。找该种的其他写法。 
            Queenes[line]=0;//会开始找下一个坐标是,因为还在for循环里面,所以还是line里面。 
                    //如果真的不行,那就会在跳一次eight再来for,总可以出现。每一层的for就是在遍历
					//所有情况了。像是树的第一层,所谓回溯算法就是递归而已,递归!!! 
        }
    }
}
int main() {
    //调用回溯函数,参数0表示从棋盘的第一行开始判断,(int)型嘛 
    eight_queen(0);
    printf("摆放的方式有%d种",Counts);
    return 0;
}

  • 11
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值