八皇后问题,是一个古老而著名的问题,该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
首先我们来看下国际象棋棋盘,
接下来,我们来看一些皇后的攻击范围。
怎么样,皇后很强叭。
那如何解题呢?
其实思路很简单,我们从第一行开始放皇后,
-
第一行先放一个皇后
-
第二行再放一个皇后,且不能被第一行的皇后攻击到
-
第三行再放一个皇后,且不能被前两行的皇后攻击到
。。。
n.第n行放一个皇后,且不能被前n-1行的皇后攻击到,若第n行的皇后无论站哪都会被前面的皇后攻击到的时候,就将第n-1个皇后换一个位置摆放,再摆第n个皇后,若还不行,则继续变更第n-1个皇后的位置。若第n-1个皇后也已摆放过所有位置还不行,则开始变更第n-2个皇后的位置。
以此下去,直到能摆放下最后一个皇后,则算找到一种解法。找到一种解法后,看看最后一行的皇后还能不能往后放,若不能,撤回最后一行皇后,回到上一行,变更上一行皇后的位置,然后再摆最后一行的皇后。这样下去,遍历完整个棋盘,就能找到所有的摆法。
看下代码实现,
#include<stdio.h>
#include<math.h>
int max=8,sum=0,a[8];
void show(){ //显示每次成功后整个界面的坐标
for(int i=0;i<max;i++){
printf("(%d,%d)\t",i,a[i]);
}
printf("\n");
}
int check(int n){
for(int i=0;i<n;i++){ //这里只需要比较到已知就行
if(a[i]==a[n]||abs(a[n]-a[i])==(n-i))//这里比较关键,就是判断现在放下的皇后是否与之前
return 0 ; //放下的皇后有冲突(即不同列,不同对角线,因为之前有
}
return 1; //之前有调用 eightQueen(n+1); //保证了不同行
}
int eightQueen(int n){
int i;
if(n<max){
for(i=0;i<max;i++){
a[n]=i;
if(check(n))
eightQueen(n+1);
}
}
else{
sum++;
show();
}
}
int main(){
eightQueen(0); //从第零行开始
printf("%d",sum);
}