EigheQueens

八皇后问题

问题

八皇后问题是经典回溯算法问题,指的是一张8*8的棋盘,放八颗棋子,使得任意两个棋子之间不在同一行同一列,且不在斜对角线上,求其有多少种解法。

分析

先考虑手动模拟这个算法,从第一行开始放,不能同行,所以每一行放一个,放的时候看跟之前的有没有同列或同对角线,没有就可以放下去,放够八个就是一个满足的解。得出一个可行解并不难,难在把所有可行解都找到,这时候就到计算机出马了。

引用一个数组,x[i]。其中,i代表行数,x[i]的具体数值代表列。任意两个棋子,用x[i]和x[j]表示,不同行:i!=j,不同列:x[i]!=x[j] ,不在同一对角线上:abs((j-k))!=abs(x[j]-x[k]),abs代表取绝对值,满足这三个条件既可放棋。

int place(int k) //判定条件
{
    for (int i = 1; i<k; i++)  //依次与以下棋子进行比较
    {
        if (x[i]==x[k]||abs(i-k)==abs(x[i]-x[k])) {
            return 0;
        }
    }
    return 1;
}

放棋步骤可以用递归加一个循环完成,递归对于新的一行,循环对于该行的列。对于递归,具体思考起来很复杂,不过这个是电脑的工作。编写起来,只需要完成两点,递归跳出条件和递归语句。条件为下够八个棋子,既i>8时就不能在下棋子了。语句为该行所有列进行判定,满足条件往下递归。

void traverse(int t)   //递归遍历
{
    if (t>num)  //递归跳出条件
    {
      sum++;   //解法加一
    }
      else {
        for (int j=1; j<=num; j++) //对每列进行判定
         {
            x[t]=j;   //对列进行赋值
            if (place(t))    //满足条件,往下递归
            {
                traverse(t+1);
            }
        }
    }

}

在主函数里进行数值的初始化,函数的调用即可完成。最后得出的结果为92种。

完整代码

#include <stdio.h>
#include <math.h>
//类比于八叉树,抽象出x[i],i为行,x[i]的数值为列。判定条件有2,1是同行同列不等,既i!=k,x[i]!=x[k],2是不在对角线上,既abs((j-k))!=abs(x[j]-x[k]),abs为取绝对值。
static int x[9];   //static设置全局变量
static int num;
static int sum;
int place(int k) //判定条件
{
    for (int i = 1; i<k; i++) {
        if (x[i]==x[k]||abs(i-k)==abs(x[i]-x[k])) {
            return 0;
        }
    }
    return 1;
}
void traverse(int t)   //递归遍历
{
    if (t>num)  //递归跳出条件
    {
      sum++;   //解法加一
    }
      else {
        for (int j=1; j<=num; j++) {
            x[t]=j;
            if (place(t))    //满足条件,往下递归
            {
                traverse(t+1);
            }
        }
    }

}
void main()
{
    num =8;   //八行八列
    sum =0;
    traverse(1);  //从第一行开始挨个放
    printf("解法共有:""%d""种\n",sum);

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值