一、算法说明
八皇后问题的描述:在8*8的棋盘内使 8 个皇后棋子无冲突地摆放。在国际象棋中,皇后的移动方式为横竖交叉的,所以在一个皇后的水平、竖直以及45° 的方向上都不能出现皇后。如下图:(使用特殊符号代替皇后) ——————————————————————————————————————————————————————————————————
二、算法分析
1、这里使用回溯法来解决这个问题,就是确定了解空间树的组织结构后,从开始结点(即根节点)开始,以深度优先的方式对整个解空间树进行搜索。
2、要使用回溯法求解八皇后问题首先要构建一颗解空间树,通过探索这棵解空间树来得到八皇后问题的一个解或多个解。如下图:
3、该解空间树为第一个皇后在第一个位置的摆法的解空间树,第一个皇后还有 7 中摆法。所以八皇后可以构建 8 棵解空间树。通过探索每棵解空间树,可以探索出第一个皇后布局之后的所有解。
4、通过上图,解空间树的第一个皇后在第一个位置时的结构。可以将第一个皇后看作根节点,该结点可以派生出 8 个结点,每个结点表示了第一个皇后位置不变的情况下第二个皇后可能出现的位置。可以看出第二层中第一个结点的摆放不符合问题的要求,这里以虚线画出,于是就停止向下探索,回溯到根节点,继续接着探索下一个子结点。当第一颗解空间树全部探索完成后,继续探索第二棵解空间树。
三、初步概述
本例算法使用一个二维数组 chess[8] [8]表示棋盘布局。当数组元素为 0 时,表示该位置没有放置皇后,当数组元素为 1 时,表示该位置放置了皇后。在本算法中调用了自定义函数 isCorrect(i,n,chess)来判断棋盘中的位置chess[i][n] 是否可以放置一个皇后。该函数的设计思想是判断chess[i][n] 的所在行、列、左上方、右下方、左下方、右上方的位置的状态。
四、代码实现
#include<stdio.h>
#include<string.h>
#include<conio.h>
int count = 0;
//isCorrect 函数用于判断该位置是否可以放棋子
//返回值为 1 表示可以放置,返回 0 表示不可以放置
int isCorrect(int i, int j, int(*chess)[8]){
int q, t;
for(q=i, t=0; t<8; t++){
if(chess[q][t]==1) //判断水平方向
return 0;
}
for(q=0, t=j; q<8; q++){
if(chess[q][t]==1) //判断竖直方向
return 0;
}
for(q=i-1, t=j-1; q>=0 && t>=0; q--, t--) //判断左上方
if(chess[q][t]==1)
return 0;
for(q=i+1, t=j+1; q<8 && t<8; q++, t++) //判断右下方
if(chess[q][t]==1)
return 0;
for(q=i-1, t=j+1; q>=0 && t<8; q--, t++) //判断右上方
if(chess[q][t]==1)
return 0;
for(q=i+1, t=j-1; q<8 && t>=0; q++, t--) //判断左下方
if(chess[q][t]==1)
return 0;
return 1;
}
//eightqueen 函数实现八皇后问题的回溯法求解
//用 0-1 矩阵表示八皇后的棋盘面,0 表示未放置棋子,1 表示放置棋子了
void eightqueen(int n, int(*chess)[8]){
int i, j;
if(n==8){ //得到一个解
for(i=0; i<8; i++){ //将这个解的布局输出
for(j=0; j<8; j++)
printf("%d", chess[i][j]);
printf("\n");
}
printf("\n");
count++; //解的数量 +1
return;
}
for(i=0; i<8; i++){
if(isCorrect(i, n, chess)){ //判断是否可以放置棋子
chess[i][n] = 1; //放置棋子
eightqueen(n+1, chess); //深度优先搜索解空间树
chess[i][n] = 0;
}
}
}
int main(){
int chess[8][8], i, j;
for(i=0; i<8; i++){ //初始化棋盘数组
for(j=0; j<8; j++)
chess[i][j] = 0;
}
eightqueen(0, chess); //执行八皇后求解函数
printf("The number of the answer for eightqueen is: %d", count);
getch();
return 0;
}
五、结束语
1、在参考本算法时,若发现有错误或者疑问,可以提出; 2、还请各位大佬提出不足与建议,谢谢! 3、感谢各位大佬的观看,谢谢!
|