回溯法是个很无聊的死算方法,没什么技巧,写这篇博客主要原因是以前思路不太清晰,现在突然想用回溯法解决一个问题时,无法快速把思路转换成代码。

-------------------------------------------------------------------------------------------------------------------------------------

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皇后问题的求解的更多相关文章

  1. 回溯法解决N皇后问题(以四皇后为例)

    以4皇后为例,其他的N皇后问题以此类推.所谓4皇后问题就是求解如何在4×4的棋盘上无冲突的摆放4个皇后棋子.在国际象棋中,皇后的移动方式为横竖交叉的,因此在任意一个皇后所在位置的水平.竖直.以及45度 ...

  2. 用试探回溯法解决N皇后问题

    学校数据结构的课程实验之一. 数据结构:(其实只用了一个二维数组) 算法:深度优先搜索,试探回溯 需求分析: 设计一个在控制台窗口运行的“n皇后问题”解决方案生成器,要求实现以下功能: 由n*n个方块 ...

  3. 递归回溯法求N皇后问题

    问题描述:在一个NN(比如44)的方格中,在每一列中放置一个皇后,要求放置的皇后不在同一行,同一列,同一斜线上,求一共有多少种放置方法,输出放置的数组. 思路解析:从(1,1)开始,一列一列的放置皇后 ...

  4. 回溯法解n皇后问题

    #include<bits/stdc++.h> using namespace std; int n,sum; int c[100]; void search(int cur){ if(c ...

  5. 回溯法之n皇后问题

    package main import ( "fmt" "math" ) //判断第k行的某一列放置是否合法 func check(col []int, k i ...

  6. javascript实现数据结构: 树和二叉树的应用--最优二叉树(赫夫曼树),回溯法与树的遍历--求集合幂集及八皇后问题

    赫夫曼树及其应用 赫夫曼(Huffman)树又称最优树,是一类带权路径长度最短的树,有着广泛的应用. 最优二叉树(Huffman树) 1 基本概念 ① 结点路径:从树中一个结点到另一个结点的之间的分支 ...

  7. python常用算法(7)——动态规划,回溯法

    引言:从斐波那契数列看动态规划 斐波那契数列:Fn = Fn-1 + Fn-2    ( n = 1,2     fib(1) = fib(2) = 1) 练习:使用递归和非递归的方法来求解斐波那契数 ...

  8. 【Algorithm】回溯法与深度优先遍历的异同

    1.相同点: 回溯法在实现上也是遵循深度优先的,即一步一步往前探索,而不像广度优先那样,由近及远一片一片地扫. 2.不同点 (1)访问序 深度优先遍历: 目的是“遍历”,本质是无序的.也就是说访问次序 ...

  9. 实现n皇后问题(回溯法)

    /*======================================== 功能:实现n皇后问题,这里实现4皇后问题 算法:回溯法 ============================= ...

随机推荐

  1. 使用XMLHttpRequest对象完成原生的AJAX请求

    1.大家眼中的Ajax 说到Ajax,只要有过前端开发经验的童鞋一定都不陌生,大都知道它就是一种与后端之间的通信技术,通过这个神奇的家伙,我们不用像传统表单那样填完信息一点提交就呼啦呼啦跳转了.Aja ...

  2. VB.Net日期格式化的5种使用方法

    VB.Net日期(时间)格式化的5种使用方法 以下时间以2009年9月26号为例 第1种格式  : dd/MM/yyyy    String.Format("{0:dd/MM/yyyy}&q ...

  3. 内存保护机制及绕过方法——利用Ret2Libc绕过DEP之ZwSetInformationProcess函数

    1.    DEP内存保护机制 1.1   DEP工作原理 分析缓冲区溢出攻击,其根源在于现代计算机对数据和代码没有明确区分这一先天缺陷,就目前来看重新去设计计算机体系结构基本上是不可能的,我们只能靠 ...

  4. Solr后台管理界面配置

    配置来源 https://stackoverflow.com/questions/28043957/how-to-set-apache-solr-admin-password 注意:配置用户名密码后 ...

  5. 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 ...

  6. arch初认识

    在这里下载最新的iso镜像,一个iso里面已经包括了32和64位. 来者不善. 进去后竟然是进入字符界面,并且给各位留了一个install.txt,果然..==! 好吧,粗略看下install.txt ...

  7. 201621123005《Java程序设计》第三周作业学习总结

    201621123005<Java程序设计>第三周 学习总结 标签(空格分隔): 未分类 1. 本周学习总结 初学面向对象,会学习到很多碎片化的概念与知识.尝试学会使用思维导图将这些碎片化 ...

  8. APUE学习笔记——5.9Binary I/O 二进制读写

    概述:         二进制I/O,通常用来一次性读写结构化的数据块.(因为有时候我们要读写的数据中包含换行符或者Null字符,无法使用fgets或fputs,而使用getc和putc又需要花费太多 ...

  9. xss 防御

    系列 防御原则 第一.在输入方面对所有用户提交内容进行可靠的输入验证,提交内容包括URL.查询关键字.http头.post数据等 第二.在输出方面,在用户输内容中使用 <XMP>标签 还是 ...

  10. python的if判断补充

    python的if判断补充 exit_flag = False # 标识符 if exit_flag == False: print('exit_flag == False') exit_flag = ...