八皇后问题
8 x 8的棋盘上保证每一行、每一列和两个斜列上只有一个皇后。
递归分析
程序结构:
- 初始化
- 循环八次:
- 放置一个皇后
- 若满足防止条件则放置皇后
- 若不满足则回退,增加一步再放置
- 直到放置到最后一个皇后
自相似的关系提取
- 过程:
- 找到N个皇后的适合位置
- 划分:
- 找到第N-1个皇后合适的位置
- 找到第N个皇后的位置
- 递归终止条件
- 找到最后一个皇后的位置
算法流程
- Step1:
- 数据初始化
- Step2:
- 从col列开始摆放第n个皇后,挨个测试列是否可行,需要先测试当前位置是否安全:
- 若安全,摆放第n个皇后,并且宣布占领(横竖撇捺都要占领)
- 若未测试完所有的的行
- 递归测试下一行
- n = N-1 时打印结果
- 如果当n >= N-1时说明无法摆放或摆放完毕时需要回溯
- 从col列开始摆放第n个皇后,挨个测试列是否可行,需要先测试当前位置是否安全:
- Step3:
- 输出结果
数据结构
- place:int数组【0....7】
- 第n行皇后所占位置的列号
- 主要用于输出结果
- flag:bool数组【0....7】
- 表示col列上能放置皇后
- d1:bool数组【0....14】
- (n,col)所在上对角线上是否可以放置皇后 (n-col+7)(保证为正)
- d2:bool数组【0....14】
- (n,col)所在下对角线上是否可以放置皇后(n+col)
程序思路
-
是否能放置
- flag[col] and d1[n-col+1] and d2[n+col]
-
放置皇后
- place[n] := col;{摆放皇后}
- flag[col] := false; {宣布占领}
- d1[n-col+7] := false; {占领上对角线}
- d2[n+col] := false; {占领下对角线}
-
删除皇后(回溯:探求所有可能):
- flag[col] := true;
- d1[n-col+1] := true;
- d2[n+col] := true;
代码
/* 八皇后问题 */ #include <stdio.h> #include <iostream> using namespace std; //初始化 int place[8] = {0}; bool flag[8] = {1,1,1,1,1,1,1,1}; bool d1[15] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; bool d2[15] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; int number = 0; void print(){ int col,i,j; number++; cout<<"No."<<number<<endl; int table[8][8] = {0}; for(col = 0;col < 8;col++){ table[col][place[col]] = 1; } for(i = 0;i < 8;i++){ for(j = 0;j < 8;j++){ cout<<table[i][j]<<" "; } cout<<endl; } } void generate(int n){ int col; for(col = 0;col < 8;col++){ if(flag[col] && d1[n-col+7] && d2[n+col]){ place[n] = col; flag[col] = 0; d1[n-col+7] = 0; d2[n+col] = 0; if(n < 7){ generate(n+1); } else{ print(); } //回溯 flag[col] = 1; d1[n-col+7] = 1; d2[n+col] = 1; } } } int main(int argc, char const *argv[]) { generate(0); return 0; }
来源:https://www.cnblogs.com/ziyuemeng/p/12571903.html