八皇后(回溯法)
题目内容#
- n*n的矩阵,作为棋盘,放置n个皇后,且它们都无法攻击其他皇后,求出放置方法
- 皇后的攻击方式,沿行、列、对角线都可以攻击其它皇后
基本思想#
使用回溯法(穷举法)#
所有的回溯问题都是由三个步骤组成:choose、explore、unchoose
因此对每个问题需要知道:
- choose what? 对于这个问题,我们选择每个字符串
- how to explore?对于这个问题,我们对剩余的字符串做同样的事情。
- unchoose 做相反的操作选择
回溯法步骤#
1.Define helper(),通常我们需要在回溯问题中使用辅助函数,以接收更多参数
2.parameters:通常我们需要以下参数:
(1)要处理的对象
(2)指示正在处理的部分
(3)阶段性步骤结果,记住当前选择choose然后取消选择unchoose
(4)最终的结果,记住最终的结果
3.Base case:基本案例。定义何时将步骤结果添加到最终结果中以及何时返回
4.Use for-loop:通常需要一个for循环迭代输入,以便我们可以选择所有选项
5.Choose:在这个问题中,如果s的子串是回文,我们将它添加到步骤中
6.Explore:在这个问题中,我们想对剩余的内容做同样的事情,所以我们递归调用我们的函数
7.Un-Choose:我们退回,删除所选的方案,以尝试其他选项
具体步骤#
- 从每一行开始判断,顺序在当前行的列放入Queen,并判断Queen是否合法 (choose)
- 重复上述步骤,向下面的行走 (explore)
- 若当前行没有放入Queen的合法位置,则回退 (unchoose)
- 回退操作直到找到当前Queen的另一个合法位置,否则一直向上面的行回退
- choose
- choose
- unchoose
- choose
- 重复以上步骤
// 辅助函数,实现回溯法的三个步骤
void helper(vector<String> res, char[][] board, int rowIndex){
// 如果到最后一行,返回结果
if(rowIndex == board.length){
res.add(generate(board));
return;
}
// 依次对当前行的每列位置判断是否能放Queen
for(int colIndex = 0; colIndex < board.length; colIndex++){
if(isValid(board, rowIndex, colIndex)){
// 确定当前行Queen的位置
board[rowIndex[colIndex]] = 'Q';
// 确定完当前行的Queen之后,转到下一行,确定Queen的故事
helper(res, board, rowIndex + 1);
// 确定完Queen的位置后,对其他位置填 '.'
board[rowIndex][colIndex] = '.';
}
}
}
// 判断位置是否合法
bool bollean isValid(char[][] board, int rowIndex, int colIndex){
// 由于从第一行开始向下走,只需要判断当前行的列以及对角线的左上和右上是否有可攻击的Queen
// 判断列是否有可攻击的Queen
for(int i = 0; i < rowIndex; i++){
if(board[i][colIndex] == 'Q'){
return false;
}
}
// 判断对角线上是否有可攻击的Queen
// 左上
for(int i = rowIndex - 1, i < colIndex - 1; i >= 0 && j >= 0; i--, j--){
if(board[i][j] == 'Q'){
return false;
}
}
// 右上
for(int i = rowIndex - 1, i < colIndex + 1; i >= 0 && j < board.length 0; i--, j++){
if(board[i][j] == 'Q'){
return false;
}
}
return true;
}
// 将board初始化为 '.'
void init(char[][] board){
for(int i = 0; i < board.length; i++){
for(int j = 0; j < board.length; j++){
board[i][j];
}
}
}
// 生成一个解
vector<String> generate(char[][] board){
vector<String> res;
string s1();
int totalnums = sizeof(board) / sizeof(char);
int rows = sizeof(board[0]) / sizeof(char);
int cols = totalnums / rows;
for(int i = 0; i < rows; i++){
for(int j = 0; j < cols; j++){
s1 += board[i][j]
}
}
res.push_back(s1);
}
int main(){
int n = 8; vector<vector<String>> res; char[][] board = new char[n][n]; init(board); helper(vector<vector<String>> res , char[][] board, rowIndex);
// 输出 res return 0; }
作者:BigBender
出处:https://www.cnblogs.com/BigBender/p/12098855.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!