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皇后问题 算法:回溯法 ============================= ...
随机推荐
- zk的watcher机制的实现
转载:https://www.ibm.com/developerworks/cn/opensource/os-cn-apache-zookeeper-watcher/ http://blog.csdn ...
- poj2195
题解: 简单KM 把每一个男的和房子分离 代码: #include<cstdio> #include<cmath> #include<algorithm> #inc ...
- LeetCode OJ:Swap Nodes in Pairs(成对交换节点)
Given a linked list, swap every two adjacent nodes and return its head. For example,Given 1->2-&g ...
- linux系统挂载NTFS移动硬盘
有时候做大数据量迁移时,为了快速迁移大数据,有可能在Linux服务器上临时挂载NTFS格式的移动硬盘, 一般情况下,Linux是识别不了NTFS格式移动硬盘的(需要重编译Linux核心才能,加挂NTF ...
- 词频统计 ——Java
github地址 :https://github.com/NSDie/personal-project 一.计划表 PSP2.1 Personal Software Process Stages 预估 ...
- 获取img元素图片的实际尺寸
// Get on screen image var screenImage = $("#image"); // Create new offscreen image to tes ...
- 【SQL查询】分区查询Over
1. Over介绍 Over为开窗函数.就是把满足条件的数据分成几个区域,每个区域可以通过像现实中的“窗口”来观察统计这些数据. over不能单独使用,要和分析函数:rank(), dense_ran ...
- ubuntu16 chrome install
1,download chrome.deb from : https://www.google.com/chrome/index.html 2,double click chrome.deb and ...
- Android程序员学WEB前端(6)-CSS(1)-选择器-Sublime
转载请注明出处:http://blog.csdn.net/iwanghang/article/details/76576469 觉得博文有用,请点赞,请评论,请关注,谢谢!~ CSS外部文档链接: & ...
- 基于视觉的 SLAM/Visual Odometry (VO) 开源资料、博客和论文列表
基于视觉的 SLAM/Visual Odometry (VO) 开源资料.博客和论文列表 以下为机器翻译,具体参考原文: https://github.com/tzutalin/awesome-vis ...