EigheQueens

来源:互联网 发布:db2和oracle的sql区别 编辑:程序博客网 时间:2024/06/17 00:02

八皇后问题

问题

八皇后问题是经典回溯算法问题,指的是一张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
原创粉丝点击