华为OJ之N皇后问题(C++代码)

本文探讨了N皇后问题的解决方案,重点在于8皇后问题。通过枚举、递归和回溯思想,确保皇后在N*N棋盘上不互相攻击。关键在于检查不同行、列及对角线上的占用情况,利用bool数组记录占用状态。代码中包含checkCol、leftCross和rightCross数组,分别对应列、主对角线和从对角线的检查。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1问题描述
N皇后问题,就是如何将国际象棋中的N个皇后放在N*N的棋盘上而不会互相攻击,是一种通过枚举,再递归、回溯的思想。

2思路
以8皇后问题为例,可知在8*8二维数组中,每个点用data[i][j]表示(0 <= i,j <= 7)。
其中其主对角线上(左上到右下)的每个点的i-j+7的值都相同(范围0-14)。
其从对角线上(右上到左下)的每个点i+j的值都相同(返回0-14)。
且其中每个子方阵的主对角线之间的i-j+7的值都不同,从对角线之间的i+j的值也不同。
如在4*4的子方阵中的data[3][4]:
穿过data[3][4]的主对角线:3-4+7=6
穿过data[3][4]的从对角线:3+4=7
若是穿过data[4][4],其主对角线:4-4+7=7;从对角线:4+4=8
为何要研究这种规律呢?

因为摆放皇后时,可知N个皇后肯定在不同行,不同列,以及不同对角线上。因此每在一个不同行摆放一个皇后时,首先要检查该列是不是被占用,以及穿过该点的主、从对角线是否被占用,若是则要换列。

3具体代码

bool checkCol[]:表示每一列的占用情况,大小1*N
bool leftCross[]:表示穿过该放置点(i,j)的主对角线的占用情况,其下标为i-j+7。
bool rightCross[]:表示穿过该放置点(i,j)的从对角线的占用情况,下标为i+j。
int * *data:N*N棋盘。

#include <iostream>
#includ
### N皇后问题的C语言实现方法 N皇后问题是经典的回溯算法应用之一,目标是将N个皇后放置在N×N的棋盘上,使得任意两个皇后都不能在同一行、同一列或对角线上。以下是对这一问题的多种C语言实现方案。 #### 递归实现 该方案通过递归的方式逐行尝试放置皇后,并检查每个位置是否安全。如果找到一个合法的位置,则递归地处理下一行,直到所有皇后都被正确放置。 ```c #include <stdio.h> #include <stdlib.h> #define N 8 // 设置皇后的数量 int queen[N]; // 存储每一行皇后所在的列位置 int count = 0; // 解决方案的数量 // 判断当前位置是否安全 int isSafe(int row, int col) { for (int i = 0; i < row; i++) { if (queen[i] == col || abs(row - i) == abs(col - queen[i])) { return 0; } } return 1; } // 递归函数用于放置皇后 void placeQueen(int row) { if (row == N) { count++; return; } for (int col = 0; col < N; col++) { if (isSafe(row, col)) { queen[row] = col; placeQueen(row + 1); } } } int main() { placeQueen(0); printf("总共有 %d 种解决方案。\n", count); return 0; } ``` #### 回溯法实现 此方案使用非递归方式实现回溯法,通过栈结构模拟递归调用,从而减少函数调用开销。 ```c #include <stdio.h> #include <stdlib.h> #include <math.h> #define MAX_QUEENS 100 int x[MAX_QUEENS]; // 存储皇后的位置 int count = 0; // 解决方案的数量int N; // 检查当前放置是否有效 int isValid(int k) { for (int i = 1; i < k; i++) { if (x[i] == x[k] || abs(i - k) == abs(x[i] - x[k])) { return 0; } } return 1; } // 回溯法解决N皇后问题 void solveNQueens() { int k = 1; x[k] = 0; while (k > 0) { x[k]++; while (x[k] <= N && !isValid(k)) { x[k]++; } if (x[k] <= N) { if (k == N) { count++; } else { k++; x[k] = 0; } } else { k--; } } } int main() { printf("请输入皇后的数量: "); scanf("%d", &N); solveNQueens(); printf("总共有 %d 种解决方案。\n", count); return 0; } ``` #### 优化递归实现 该版本在递归的基础上进行了空间优化,避免不必要的重复计算。 ```c #include <stdio.h> int N; // 皇后的数量 int count = 0; // 解决方案的数量 // 检查当前列是否可以放置皇后 int canPlace(int row, int col, int *positions) { for (int i = 0; i < row; i++) { if (positions[i] == col || row - i == abs(positions[i] - col)) { return 0; } } return 1; } // 递归放置皇后 void placeQueens(int row, int *positions) { if (row == N) { count++; return; } for (int col = 0; col < N; col++) { if (canPlace(row, col, positions)) { positions[row] = col; placeQueens(row + 1, positions); } } } int main() { printf("请输入皇后的数量: "); scanf("%d", &N); int positions[N]; placeQueens(0, positions); printf("总共有 %d 种解决方案。\n", count); return 0; } ``` 以上代码展示了N皇后问题的几种常见实现方式,包括递归和非递归两种思路。每种实现都通过不同的方法确保皇后不会互相攻击,最终统计出所有可能的解决方案[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值