前言
八皇后问题是一个经典的计算机科学问题,要求在一个8×8的棋盘上放置8个皇后,使得它们互相之间不能攻击到对方。这个问题可以通过穷举和试探的方法来解决。
- 穷举法是一种解决问题的方法,它通过尝试所有可能的解决方案来找到满足条件的解。这种方法适用于解空间较小的问题,例如八皇后问题、0/1 背包问题等。在 C 语言中,我们可以通过编写循环来遍历所有可能的解决方案,并判断是否满足条件。
- 试探法是一种基于经验或启发式规则的方法,它通过逐步搜索解空间来找到满足条件的解。这种方法适用于解空间较大或问题具有启发式特征的情况。在 C 语言中,我们可以通过编写递归或循环来实现试探法,例如深度优先搜索(DFS)或广度优先搜索(BFS)。
十二、C语言程序开发
12.1~3 自顶向下、逐步求精;结构化程序设计原则;程序风格
【重拾C语言】十二、C语言程序开发(自顶向下、逐步求精;结构化程序设计原则;程序风格)_QomolangmaH的博客-CSDN博客
https://blog.csdn.net/m0_63834988/article/details/133825033?spm=1001.2014.3001.5502 在C语言程序开发中,可以使用自顶向下、逐步求精的方法解决问题,遵循结构化程序设计原则,同时注重良好的程序风格,这可以帮助开发者编写可读性强且易于维护的代码。
12.4 八皇后——穷举与试探
12.4.1 穷举法
穷举法(Exhaustive Search)是一种常见的算法设计方法,用于在给定的搜索空间中尝试所有可能的解决方案,以找到满足特定条件的解。
- 在C语言中,可以使用循环结构和条件语句来实现穷举法。一般步骤如下:
- 定义问题的搜索空间和解的表示方式。
- 使用循环结构遍历搜索空间中的所有可能解。
- 对于每个可能解,使用条件语句判断是否满足问题的条件。
- 如果满足条件,执行相应的操作,例如输出结果或保存解决方案。
- 继续循环,直到遍历完整个搜索空间。
- 示例:寻找一个整数的平方根
#include <stdio.h>
int main() {
int num;
printf("Enter a number: ");
scanf("%d", &num);
int i;
for (i = 0; i <= num; i ) {
if (i * i == num) {
printf("Square root of %d is %dn", num, i);
break;
}
}
if (i > num) {
printf("No square root found for %dn", num);
}
return 0;
}
通过循环遍历从0到输入的数字,逐个尝试每个可能的平方根。如果找到一个平方根,就输出结果并结束循环。如果循环结束后仍然没有找到平方根,就输出相应的提示信息。
输出:
这只是一个简单的示例,实际上,穷举法可以应用于各种问题,包括组合优化、密码破解等。但是需要注意的是,穷举法的计算复杂度通常较高,随着搜索空间的增大,计算时间会呈指数级增长。因此,在实际应用中,需要根据问题的规模和要求,权衡计算时间和解的准确性。
12.4.2 试探法
试探法(Backtracking)是一种基于经验或启发式规则的方法,它通过逐步搜索解空间来找到满足条件的解。通常通过递归的方式进行搜索,尝试每一种可能的选择,并在满足条件的情况下继续向下搜索,如果不满足条件,则回溯到上一步选择的状态,重新选择其他可能的路径。
- 在C语言中,可以使用递归函数和条件语句来实现试探法。一般步骤如下:
- 定义问题的搜索空间和解的表示方式。
- 编写一个递归函数,在每一步选择中进行尝试,并根据条件判断是否满足问题的要求。
- 如果满足条件,执行相应的操作,例如输出结果或保存解决方案。
- 继续递归调用函数,进入下一步选择。
- 如果不满足条件,回溯到上一步选择的状态,重新选择其他可能的路径。
- 继续递归调用函数,进行下一步尝试。
- 示例:计算给定数字的阶乘
#include <stdio.h>
int factorial(int n) {
// 基本情况:当 n 为 0 或 1 时,阶乘为 1
if (n == 0 || n == 1) {
return 1;
}
// 递归情况:调用自身来计算 n 的阶乘
else {
return n * factorial(n - 1);
}
}
int main() {
int n = 5;
int result = factorial(n);
printf("%d 的阶乘为 %dn", n, result);
return 0;
}
输出:
试探法可以应用于各种问题,如组合优化、图的遍历、八皇后问题等。通过不断地试探和回溯,可以找到所有可能的解决方案。请注意,试探法的计算复杂度也可能较高,特别是在搜索空间较大时。因此,在实际应用中,需要谨慎选择搜索策略和剪枝技巧,以提高算法的效率。同时,合理设计问题的表示方式和条件判断,可以帮助减少搜索空间,加快求解过程。
12.4.3 穷举与试探(八皇后问题)-递归实现
穷举法是一种简单但低效的解决方法,它通过尝试所有可能的皇后布局来找到满足条件的解。具体步骤如下:
- 从第一行开始,依次尝试在每一列放置皇后。
- 检查当前的布局是否满足没有皇后互相攻击的条件。
- 如果满足条件,继续到下一行,重复上述步骤。
- 如果在某一行无法找到合适的位置放置皇后,回溯到上一行,尝试下一个列。
- 当放置完最后一行的皇后并且满足条件时,找到一个解。
穷举法的缺点是需要尝试大量的组合,因此在较大的棋盘上效率较低。
代码语言:javascript复制#include <stdio.h>
#define N 8
void printBoard(int board[N][N]) {
for (int i = 0; i < N; i ) {
for (int j = 0; j < N; j ) {
printf("%c ", board[i][j] ? 'Q' : '.');
}
printf("n");
}
printf("n");
}
int isSafe(int board[N][N], int row, int col) {
// 检查当前位置的左侧是否有皇后
for (int i = 0; i < col; i ) {
if (board[row][i]) {
return 0;
}
}
// 检查当前位置的左上方是否有皇后
for (int i = row, j = col; i >= 0 && j >= 0; i--, j--) {
if (board[i][j]) {
return 0;
}
}
// 检查当前位置的左下方是否有皇后
for (int i = row, j = col; i < N && j >= 0; i , j--) {
if (board[i][j]) {
return 0;
}
}
return 1;
}
int count = 0; // 全局变量用于计数解的数量
void solveNQueens(int board[N][N], int col) {
// 所有皇后都放置完毕,打印解决方案,增加解的数量并返回
if (col == N) {
printBoard(board);
count ;
return;
}
// 逐行尝试放置皇后
for (int i = 0; i < N; i ) {
if (isSafe(board, i, col)) {
// 放置皇后
board[i][col] = 1;
// 递归地尝试下一列
solveNQueens(board, col 1);
// 回溯,撤销当前位置的皇后
board[i][col] = 0;
}
}
}
int main() {
int board[N][N] = {0};
solveNQueens(board, 0);
printf("Number of solutions: %dn", count);
return 0;
}
输出: