八皇后c语言解析(适用于新手)

问题描述:国际象棋棋手马克斯于1848年提出:在8*8的国际象棋放八个皇后,使其不能相互攻击,即任意两个皇后不能处于同一行,同一列,或者同一斜线上。(不知道为啥的朋友可以去了解以下国际象棋的基本规则),高斯认为有76种解法,计算机出来后解出92种解法。(终于在数学上可以超过一下天才儿童高斯了o(^▽^)o)

主要算法:回溯

算法详解:使用一个一维数组queue[8],因为一行只用放置一个皇后,所以我们可以用queue[i]的值来存储这一行放置的列数,而i表示行数,这样我们只需要一个一维数组就可以表示出8行棋盘每行只放置一个皇后的状态。算法的原理主要是:

1.从第1行开始的第一个位置开始放置;

2.判断此时放置的位置是否可以放置;(设置一个函数判断是否可以放置)

3.若判断可以放置那么从下一行的第一列开始设置下一行。若是行数已经到了8行,那么打印所有的放置位置。若此时的放置位置不可以放置,那么更改此时放置的位置。(此时,采用回溯算法,若可以放置则到下一行,不可以放置则返回到上一行。若是不能理解,先去了解递归时的系统栈)

4.打印出结果

函数详解:

check(int n)//check函数来表示当前位置是否可以放置,n表示当前的放置行数。其主要内容如下:

 for(i=0;i<n;i++)
    {
         if(queue[i]==queue[n]||abs(queue[i]-queue[n])==(n-i))
           {
               return 0;
               }
    }

    return 1;

for循环表示从第1行开始直到现在放置的这一行来检查是否符合放置规则。因为i和n不相同,所以不需要检查在同一行的情况。

只需要检查是否在同一列或者在同一斜线的情况。queue[i]==queue[n]就表示在同一列上有两个皇后了,注意queue[i]和queue[n]的值代表列,所以他们两的值不可以相同。对于斜线的检查,数学原理为|y1-y2|==|x1-x2|。在我们设置的变量中queue[i]和queue[n]的值就相当于x1和x2。i和n就相当于y1和y2.abs是绝对值函数。

put(int n)//放置函数,其内容如下:

 int i=0;
    for(i=0;i<max;i++)
        {
        queue[n]=i;
        if(check(n)){
            if(n==max-1)
                show();
            else
                put(n+1);
        }

    }

max可在宏定义中定义其值为8。由第1行开始放置,并且判断是否可以放置,之后进入回溯。满8行后打印即可。

完整程序如下,已经在codeblock上运行过了:

#include<stdio.h>
#define max 8
int queue[max];
int sum=0;
void show()
{
    int i=0;
    for(i=0;i<max;i++){
        printf("(%d,%d)",i,queue[i]);
    }
    sum++;
    printf("\n");
}
int check(int n)
{
    int i=0;
    for(i=0;i<n;i++)
    {
         if(queue[i]==queue[n]||abs(queue[i]-queue[n])==(n-i))
           {
               return 0;
               }
    }
    return 1;
}
void put(int n)
{
    int i=0;
    for(i=0;i<max;i++)
        {
        queue[n]=i;
        if(check(n)){
            if(n==max-1)
                show();
            else
                put(n+1);
        }
    }
}
void main()
{
    put(0);
    printf("\n%d",sum);
}



































猜你喜欢

转载自blog.csdn.net/weixin_34855969/article/details/79743640