C++使用回溯法实现N皇后问题的求解
回溯法是个很无聊的死算方法,没什么技巧,写这篇博客主要原因是以前思路不太清晰,现在突然想用回溯法解决一个问题时,无法快速把思路转换成代码。
-------------------------------------------------------------------------------------------------------------------------------------
N-皇后问题描述:在N*N的棋盘上,每一行放置一个皇后,使得任意皇后之间不能互相攻击。求放置方法。
(因为国际象棋中皇后可以走横竖斜线,所以相当于是任意2个棋子不处在同一行、列或对角线)
思路是设解为四维向量x,第i行把皇后放在第x[i]列。(这里把行号列号均从0开始)然后像下面这样一个个找:
初始:x为空。令x[0] = 0,然后寻找第1个符合约束(简称“合法”)的x[1],可得x[1] = 2。再寻找第1个合法的x[2],发现无论是0、1、2、3都不行。于是就得回退了。
退到x[1],寻找下一个符合约束的x[1],即令x[1]=3,再继续找x[2]。若找到一组解则回退,寻找下一组解,一直到无法回退为止。
(比如x = { 1, 3, 0, 2 },添加x到解集中,之后回退寻找下一个合法的x[2]。此时发现1、2、3都不行,于是再回退,寻找下一个合法的x[1]。)
#include <stdio.h>
#include <vector>
#include <array>
using namespace std; template <int N>
class QueenProblem
{
public:
explicit QueenProblem()
{
for (int i = 0; i < N; i++)
x[i] = -1;
run();
} size_t size() const { return results.size(); }
const array<int, N>& operator[](size_t k) const { return results[k]; } private:
vector<array<int, N>> results; // 解集 // 解向量, (i,x[i])代表第i行第x[i]列放置皇后
// 其中行号和列号都是从0开始, 即范围为[0,N)
// x[i]=-1则代表第i行的位置并未确定
array<int, N> x; void run()
{
int k = 0;
while (k >= 0)
{
x[k]++; // 尝试新的位置
while (x[k] < N && !CheckRow(k))
x[k]++; if (x[k] == N) // 当前行无法放置皇后, 回溯
{
x[k--] = -1;
continue;
} if (k == N - 1) // 找到一组解, 将其添加到解集中并回溯寻找新的解
{
results.emplace_back(x);
x[k--] = -1;
}
else // 第0到k行合法, 尝试设置第k+1行的皇后
{
k++;
}
}
} // 假设第0到k-1行均成功放置皇后并且合法(即其中任意2个皇后不处于同一行/列/对角线)
// 判断第k行的放置方案是否合法, 若合法则返回true, 否则返回false
bool CheckRow(int k)
{
for (int i = 0; i < k; i++)
if (x[i] == x[k] || abs(x[i] - x[k]) == abs(i - k))
return false;
return true;
}
}; int main()
{
#define PrintNQueenSolNum(N) printf("%2d皇后的解的数量: %7ld\n", N, \
QueenProblem<N>().size());
PrintNQueenSolNum(1);
PrintNQueenSolNum(2);
PrintNQueenSolNum(3);
PrintNQueenSolNum(4);
PrintNQueenSolNum(5);
PrintNQueenSolNum(6);
PrintNQueenSolNum(7);
PrintNQueenSolNum(8);
PrintNQueenSolNum(9);
PrintNQueenSolNum(10);
PrintNQueenSolNum(11);
PrintNQueenSolNum(12);
PrintNQueenSolNum(13);
PrintNQueenSolNum(14);
PrintNQueenSolNum(15);
printf("其中, 4皇后的解为:\n");
QueenProblem<4> sol;
for (size_t i = 0; i < sol.size(); i++)
{
printf("第%d组解: ", i);
for (int x : sol[i])
printf("%d ", x);
printf("\n");
}
return 0;
}

直接贴包装后的代码了,编译期确定N,所以不支持运行时确定N是多少。算到15皇后就完了。
体现回溯法的核心代码就是成员函数run()
C++使用回溯法实现N皇后问题的求解的更多相关文章
- 回溯法解决N皇后问题(以四皇后为例)
以4皇后为例,其他的N皇后问题以此类推.所谓4皇后问题就是求解如何在4×4的棋盘上无冲突的摆放4个皇后棋子.在国际象棋中,皇后的移动方式为横竖交叉的,因此在任意一个皇后所在位置的水平.竖直.以及45度 ...
- 用试探回溯法解决N皇后问题
学校数据结构的课程实验之一. 数据结构:(其实只用了一个二维数组) 算法:深度优先搜索,试探回溯 需求分析: 设计一个在控制台窗口运行的“n皇后问题”解决方案生成器,要求实现以下功能: 由n*n个方块 ...
- 递归回溯法求N皇后问题
问题描述:在一个NN(比如44)的方格中,在每一列中放置一个皇后,要求放置的皇后不在同一行,同一列,同一斜线上,求一共有多少种放置方法,输出放置的数组. 思路解析:从(1,1)开始,一列一列的放置皇后 ...
- 回溯法解n皇后问题
#include<bits/stdc++.h> using namespace std; int n,sum; int c[100]; void search(int cur){ if(c ...
- 回溯法之n皇后问题
package main import ( "fmt" "math" ) //判断第k行的某一列放置是否合法 func check(col []int, k i ...
- javascript实现数据结构: 树和二叉树的应用--最优二叉树(赫夫曼树),回溯法与树的遍历--求集合幂集及八皇后问题
赫夫曼树及其应用 赫夫曼(Huffman)树又称最优树,是一类带权路径长度最短的树,有着广泛的应用. 最优二叉树(Huffman树) 1 基本概念 ① 结点路径:从树中一个结点到另一个结点的之间的分支 ...
- python常用算法(7)——动态规划,回溯法
引言:从斐波那契数列看动态规划 斐波那契数列:Fn = Fn-1 + Fn-2 ( n = 1,2 fib(1) = fib(2) = 1) 练习:使用递归和非递归的方法来求解斐波那契数 ...
- 【Algorithm】回溯法与深度优先遍历的异同
1.相同点: 回溯法在实现上也是遵循深度优先的,即一步一步往前探索,而不像广度优先那样,由近及远一片一片地扫. 2.不同点 (1)访问序 深度优先遍历: 目的是“遍历”,本质是无序的.也就是说访问次序 ...
- 实现n皇后问题(回溯法)
/*======================================== 功能:实现n皇后问题,这里实现4皇后问题 算法:回溯法 ============================= ...
随机推荐
- 037——VUE中表单控件处理之表单修饰符:lazy/number/trim
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- LeetCode OJ:Search in Rotated Sorted Array II(翻转排序数组的查找)
Follow up for "Search in Rotated Sorted Array":What if duplicates are allowed? Would this ...
- L154
Several possessions of the late physicist's Stephen Hawking will be included in an upcoming auction ...
- Shell 命令行批量处理图片文件名
Shell 命令行批量处理图片文件名 从网上下载了一堆图片,有的是*.jpg的,有的是*.jpeg的.并且文件名有长有短,很是糟心.因此,我想把这些文件给全部整理好,当然是用shell来处理啦! 说干 ...
- 【跟着stackoverflow学Pandas】Select rows from a DataFrame based on values in a column -pandas 筛选
最近做一个系列博客,跟着stackoverflow学Pandas. 以 pandas作为关键词,在stackoverflow中进行搜索,随后安照 votes 数目进行排序: https://stack ...
- 我也说说Emacs吧(1) - Emacs和Vi我们都学
好友幻神的<Emacs之魂>正在火热连载中,群里人起哄要给他捧捧场. 作为一个学习Emacs屡败屡战的用户,这个场还是值得捧一下的.至少我是买了HHKB键盘的... 从我的键盘说起 - 有 ...
- Java 保存对象到文件并恢复 ObjectOutputStream/ObjectInputStream
1.从inputFile文件中获取内容,读入到set对象: 2.然后通过ObjectOutputStream将该对象保存到outputFile文件中: 3.最后通过ObjectInputStream从 ...
- C:源文件编译过程
可以大致概括为3个阶段: 源文件 → 汇编代码(文本) 汇编代码 → 机器语言(二进制) 各个目标文件的处理 详细过程: 预编译处理 Pre-processing(*.c/ *.cpp → *.i) ...
- skywalking探针tomcat8.0.28报错解决
在部署skywalking agent的时候遇到一个异常 环境如下: tomcat8.0.28 catalina.out 日志报如下错误 30-Apr-2019 10:25:57.664 INFO [ ...
- 报错【Expression user.achievement is undefined on 】