文章目录
问题引入
N皇后问题是一个经典的问题,即在一个N×N的棋盘上放置N个皇后,使得它们互相不能攻击到对方。皇后可以攻击到同一行、同一列和同一对角线上的其他皇后。这个问题的目标是找到所有满足条件的皇后放置方式。在实际应用中,通常采用回溯算法来解决N皇后问题。
一、基本步骤
- 初始化一个N×N的棋盘,初始时所有格子都为空。
- 从第一行开始逐行放置皇后,每一行只能放置一个皇后。
- 在放置皇后时,需要检查当前位置是否和之前已经放置的皇后位置冲突,即同一列、同一对角线上是否已经有皇后。
- 如果当前位置可以放置皇后,则继续放置下一行的皇后;如果不能放置,则回溯到上一行,重新选择位置放置皇后。
- 当所有皇后都放置完毕时,得到一个解,记录下来并继续搜索其他可能的解。
- 继续搜索直到找到所有可能的解。
二、算法思路
1.伪代码
代码如下(示例):(跟八皇后伪代码一模一样,懂了即可直接跳过哈)
function solveNQueens(n):
result = [] // 用于存放所有解的列表
board = createEmptyBoard(n) // 创建一个空的棋盘
// 定义递归函数来放置皇后
function placeQueens(row):
if row == n:
result.append(board.copy()) // 找到一个解,将当前棋盘状态添加到结果列表中
return
for col from 0 to n-1:
if isSafe(board, row, col):
board[row][col] = 'Q' // 在当前位置放置皇后
placeQueens(row + 1) // 继续放置下一行的皇后
board[row][col] = '.' // 回溯,将当前位置重新设为空
// 检查当前位置是否安全
function isSafe(board, row, col):
// 检查列是否冲突
for i from 0 to row-1:
if board[i][col] == 'Q':
return false
// 检查左上方对角线是否冲突
for i, j from row-1, col-1 to 0, 0:
if board[i][j] == 'Q':
return false
// 检查右上方对角线是否冲突
for i, j from row-1, col+1 to 0, n-1:
if board[i][j] == 'Q':
return false
return true
// 开始放置皇后
placeQueens(0)
return result
2.代码实现
代码如下(示例):
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
const int N=10;
int n,cnt;
int a[N];
bool check(int x,int y){
for(int i=1;i<=x;i++){
if(a[i]==y) return false; //这里的a[i]==y,表示在同一列上
if(i+a[i]==x+y) return false;//这里i+a[i]==x+y,表示在右对角线上
if(i-a[i]==x-y) return false;//同理,在左对角线上
}
return true;
}
void dfs(int row){ //表示第row行皇后放在什么地方
if(row==n+1){ //所有皇后都已经成功放置在棋盘上,即找到了一种解法
cnt++; //产生一组解
return;
}
for(int i=1;i<=n;i++){
if(check(row,i)){
a[row]=i;
dfs(row+1);
a[row]=0;
}
}
}
int main() {
cin>>n; //输入的是几个皇后
dfs(1);//回溯到第一次,dfs(1)表示从第一行开始放置皇后。
// 回溯算法的特点是在搜索过程中,如果发现当前路径无法找到解,就会回溯到上一个状态继续搜索。
// 在这里,dfs(1)表示从第一行开始放置皇后,并且在放置第一行皇后的过程中,会递归地处理下一行皇后的放置。
// 如果在放置第二行皇后时发现无法找到解,就会回溯到放置第一行皇后的状态,继续尝试其他放置方式。
// 因此,dfs(1)表示从第一行开始放置皇后,并在需要时回溯到第一行重新开始搜索。
cout<<cnt;//输出的是有多少种放法
return 0;
}
三、结果
八皇后: 四皇后:
当然,我在代码中设置的N=10,最多到10个,申请了数组a[N] ,10个空间,如有需要可以自我修改。
四、总结
通过回溯法,可以找到所有满足条件的N皇后问题的解。在实现时,可以使用递归函数来实现回溯过程,并在递归函数中进行位置的选择和判断。同时,可以使用一个数组来记录已经放置的皇后位置,以便进行冲突检查。