八皇后问题描述
1.什么是八皇后问题
在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。
即在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上
解析算法:
1.首先我们并不需要一开始就接设计8x8的二维数组(这个二维数组只是比较好说明问题。),如果我们以行移动为基准的话,我们只要统计该行的每一列,以及它的左斜线和它的右斜线能否放皇后就可以了。
2.所以我们只需要3个数组分别代表就行了。这里肯定有人说列用数组好代表,那左斜线和右斜线该用数组怎么表示呢!其实我们不难发现,左斜线的值得规律为它得i+j=7(行加列的值),右斜线的规律为i-j+7
备注 i为行,j为列,左斜线有15条,右斜线也有15条。因为是8 x 8的矩阵
画个图一下就明白了。
if((!col[j])&&(!left[i+j])&&(!right[i-j+7])) //判段能否放皇后
递归
#include<stdio.h>
#include <conio.h>
int count=0; //计数,一共有多少组合
int col[8]={0},right[15]={0},left[15]={0};//col列数,left左斜线 right 右斜线,
int q[8]={0};
void print(){
printf("=======================\n\n");
for(int t=0;t<8;t++){
printf("%d行%d列\n",t,q[t]);
}
count++;
//printf("=======================");
}
void queen(int i){
int j;
for(j=0;j<8;++j){
if((!col[j])&&(!left[i+j])&&(!right[i-j+7])){ //判段能否放皇后
col[j]=left[i+j]=right[i-j+7]=1; //修改列值和左斜线 右斜线
//修改 col列数,left左斜线 right 右斜线的值 置1
q[i]=j; //q[i]下标为行,存储的值为列
if(i<7){ //判断行数是否到达第七行,如果到达第七行,超过直接输出
queen(i+1); //回溯到下一行
}
else{
//进入else无非就是到了第七行
print();
}
col[j]=left[i+j]=right[i-j+7]=0;//抹皇后 两种情况 1.该行放不了回溯到上一层,上一层皇后放的有问题2.到达第七行
}
}
}
int main(){
queen(0);
printf("count = %d\n",count);
}
非递归
#include<stdio.h>
#include <conio.h>
int count=0; //计数,一共有多少组合
int col[8]={0},right[15]={0},left[15]={0};//col列数,left左斜线 right 右斜线,
int q[8]={0};//存储皇后的数组
void print(){
printf("=======================\n\n");
for(int t=0;t<8;t++){
printf("%d行%d列\n",t,q[t]);
}
count++;
printf("count=%d",count);
}
int main(){
int i=0,j=0;
while(i<8){
//@ 1
while(j<8){
//@2
if((!col[j])&&(!left[i+j])&&(!right[i-j+7])) //判段能否放皇后
break; //从break跳出 找到满足条件的皇后
j++;
//如果循环了8次还没找到,就说明上一个的皇后有问题
}
if(j<8){
//从break跳转出来
col[j]=left[i+j]=right[i-j+7]=1; //修改列值和左斜线 右斜线
q[i]=j; //存皇后
if(i<7){
//@3 进入下一行,这个时候注意列值要从头开始
j=0;
i++;
}
else{
//行数已经到达第七行
print(); // 输出
col[j]=left[i+j]=right[i-j+7]=0; //抹皇后,继续查找
j++; //从第7行被抹皇后的后面继续查找
}
}
else{
//这个时候j是正常跳转出来,循环完毕
//当前行放不了,回到上一行
i--; //回到上一行
j=q[i]; //j保存上一行中的皇后的列数
col[j]=left[i+j]=right[i-j+7]=0; //抹皇后
j++; // 从错误的皇后列数,继续往后找
//注意:这里一定是先要抹皇后,在往后找。如果先往后面找的话,抹皇后就出现了问题。
}
}
}
一共92中解。这里非递归出现了问题,我尝试在main函数里输出count总数,但就是输出不出来,于是我只能转入输出函数中,输出每一中结果。