八皇后介绍
八皇后问题: 在一个8x8的棋盘上放置8个皇后,使得任何两个皇后都不能处于同一行、同一列或同一斜线上。问有多少种方法可以放置这8个皇后?
解题思路
为了方便计算我们将问题简化为4皇后问题
在4*4的棋盘上放4个皇后,首先在数列1列1行放第一个皇后,再将第二个皇后放到第二行的第一列(因为不能为同一行所以我们自动跳过再第一行放皇后),再进行判断是否为同一列或同一斜线上:若如此则返回重新放入二号皇后,进行循环;若非如此,则继续在第三行第三列放入第三个皇后,进行以上方式的循环
(注:此方法称之为回溯法,在很多编程时都可用到,非常方便)
主题思路
分区编写
根据上方的设想可以看出此代码我们将其分为4个函数来完成最好:首先设立一个主函数再其中设立第一个分函数queen,queen函数中我们目的为判断数列是否符合要求的分类去向,将符合的数列打印,打印时需要设立第二个分函数cout_cheek主要用来将具体的图示打印,将不符合的数列推入第三个分函数notdanger,而notdanger函数主要用来判断位置是否安全。
代码形成
queen函数使用if、else语句将类别分开,在else语句中加入for循环,其中套入notdanger函数,如果notdanger函数判断位置不安全则回溯到for循环中重新输入第一个皇后,若notdanger函数判断位置安全则进入queen函数进行循环
代码整合
下面将代码实现:
#include <stdio.h>
int cnt = 0;//解法个数
int qq[8][8] = { 0 };
void cout_cheek(int aa[][8], int n) {//输出二维数组
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
printf("%d ", aa[i][j]);
}
printf("\n");
}
printf("\n");
}
int notdanger(int qq[][8], int n, int k) {//判断某位置是否安全
for (int i = 0; i < n; i++) {
if (qq[i][k] == 1) return 0;//该列
}
for (int i = n, j = k; i >= 0 && j >= 0; i--, j--) {//左上角
if (qq[i][j] == 1) return 0;
}
for (int i = n, j = k; i >= 0 && j < 8; i--, j++) {//右上角
if (qq[i][j] == 1) return 0;
}
return 1;
}
void queen(int qq[][8], int n) {
if (8 == n) {
cnt++;
printf("第%d种答案:\n", cnt);
cout_cheek(qq, 8);
}
else {
for (int k = 0; k < 8; k++) {
if (notdanger(qq, n, k)) {
qq[n][k] = 1;
queen(qq, n + 1);
qq[n][k] = 0;
}
}
}
}
int main() {
queen(qq, 0);
printf("cnt==%d\n", cnt);
return 0;
}
代码总结
此代码主要运用了回溯的思想,灵活运用到各种问题中会有很好的效果