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皇后问题 算法:回溯法 ============================= ...
随机推荐
- dump相关
命令:jmap -dump:format=b,file=/tmp/dump.hprof pid jstack -l 30087 >> text.txt
- caffe:自己搭建网络来训练
1.准备样本 要训练自己的样本,首先需要把样本准备好,需要准备的是训练集和测试集,caffe支持直接使用图片,当然把样本转换为leveldb或lmdb格式的话训练起来会更快一点.这里我先偷个懒,直接使 ...
- 如何解决虚拟机中的ubuntu系统方向键与退格键不能正常使用的问题
问题描述: 在虚拟机中安装了ubuntu系统,打开vi,当vi进入insert模式后,后退键(backspace)不能删除字符,上下左右键也对应了W,S,A,D. 解决办法: cp /etc/vim/ ...
- Ubuntu 13.10 如何修改背景色--豆沙绿
如何修改Ubunut 13.10的窗口背景色,在网上找到了多资料,安装了dconf,Unity Tweak Tool,GNOME Color Chooser都无法修改背景色. 最后,还是直接去修改主题 ...
- jinfo用法说明
以下几种用法 -flags pid :打印当前VM的参数 -flag <name> pid:打印指定JVM的参数值 -flag [+|-]<name> pid:设置指定JVM参 ...
- 20165202 2017-2018-2 《Java程序设计》第9周学习总结
教材学习内容总结 Ch13 URL类 URL类是java.net包中的一个重要的类,URL的实例封装着一个统一资源定位符,使用URL创建对象的应用程序称作客户端程序. 一个URL对象通常包含最基本的三 ...
- iOS 阶段学习第三天笔记(运算符)
iOS学习(C语言)知识点整理笔记 1.运算符 一.算术运算符 1)表达式由变量.常量.运算符构成,有确定的类型和值 2)算术运算符包括: +(加),-(减),*(乘),/(除),%(模) 3)算术运 ...
- React-Native基础_5.列表视图ListView 网络数据展示
//获取网络数据 并用列表展示 豆瓣Top250 api /** * Sample React Native App * https://github.com/facebook/react-nativ ...
- fedora26 Mysql 开放远程链接服务
下载安装MySQL 用以下指令安装 $ dnf install mysql-server 注意:Fedora默认安装mariadb 安装完成之后,用以下指令测试 $ mysql --version 开 ...
- SaltStack简明教程
第1章 SaltStack简明教程 1.1 SaltStack简介 SaltStack是基于Python开发的一套C/S架构配置管理工具(功能不仅仅是配置管理,如使用salt-cloud配置AWS E ...