一、八皇后问题

  八皇后问题是一个以国际象棋为背景的问题:如何能够在8 × 8 的国际象棋棋盘上放置八个皇后Queen),使得任何一个皇后都无法直接吃掉其他的皇后。为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。八皇后问题可以推广为更一般的N皇后摆放问题:这时棋盘的大小变为 N ×N,而皇后个数也变成 N当且仅当 n = 1 或 n ≥ 4 时问题有解。

二、利用回溯法递归求解N-皇后问题

  生成棋盘所有皇后摆放的可能配置,并打印满足给定约束的配置。回溯算法的思想是将皇后从最左边的列开始一一放置在不同的列中。 当我们将皇后放在一列中时,检查是否与已经放置的皇后发生冲突。 在当前列中,如果找到没有冲突的行,则将该行和列标记为解决方案的一部分。 如果由于冲突而找不到这样的行,那么我们将回溯并返回 false

  首先是从棋盘最左边的列开始摆放皇后。

算法主要内容:

1. 当 col = N 时,所有皇后摆放完毕,问题有解

2. 算法从每一列的每一行来推进问题的求解:

  • a) 如果该位置 (i, j) 能把皇后无冲突的放进去,标记这个位置为 1,然后一直递归求解下一列的某行位置能否求解问题;
  • b) 如果这个位置能摆放皇后则返回 true;
  • c) 如果放置皇后并不能解决问题,取消标记此 (i, j)(回溯),然后转到步骤(a)尝试其他行。

3. 如果所有列所有行都尝试探索过后依然无解,返回 false(回溯)。

三、N-皇后问题的实现

  检查当前位置放置皇后会与之前放置的皇后冲突。这里的时间复杂度为 O(N)。

 1     /**
2 * 用于检查是否可以将Queen放在当前位置上
3 *
4 * @param board
5 * @param row
6 * @param col
7 * @return
8 */
9 private boolean isSafe(int[][] board, int row, int col) {
10 int i, j;
11
12 /* 是否在同一行(左侧) */
13 for (i = 0; i < col; i++)
14 if (board[row][i] == 1)
15 return false;
16
17 /* 是否在反对角线方向上 */
18 for (i = row, j = col; i >= 0 && j >= 0; i--, j--)
19 if (board[i][j] == 1)
20 return false;
21
22 /* 是否在对角线方向上 */
23 for (i = row, j = col; j >= 0 && i < N; i++, j--)
24 if (board[i][j] == 1)
25 return false;
26
27 return true;
28 }

  通过递归方式来探索问题的解,在所有位置尝试完之前,探索问题的解失败时通过回溯来寻找下一个皇后的摆放位置,回溯同时把摆放位置的标记复原。对于N皇后的时间复杂度,分析起来有点复杂,但从中可以分析其时间复杂度为 O(N3)。

 1     /**
2 * 递归求解N-Queen问题
3 *
4 * @param board
5 * @param col
6 * @return
7 */
8 private boolean solveNQUtils(int[][] board, int col) {
9 /* 如果所有皇后都被放置, 然后返回true */
10 if (col >= N)
11 return true;
12
13 /* 考虑当前col能否摆放Queen */
14 for (int i = 0; i < N; i++) {
15 /* 当前位置是否能摆放Queen */
16 if (isSafe(board, i, col)) {
17 board[i][col] = 1;
18
19 /* 再次摆放Queen, 如果成功直接返回true */
20 if (solveNQUtils(board, col + 1)) {
21 return true;
22 }
23
24 /* 这是在某列无法放Queen回溯时把queen移走 */
25 board[i][col] = 0;
26 }
27 }
28
29 return false;
30 }

本文源代码:

  1 package algorithm;
2
3 /**
4 * N皇后问题,回溯法,简单分析一下,时间复杂度大概为 O(N^3)
5 */
6 public class NQueenProblem {
7 private final int N = 8;
8
9 /**
10 * 打印符合条件的摆放棋盘
11 *
12 * @param board
13 */
14 private void printSolution(int[][] board) {
15 for (int i = 0; i < N; i++) {
16 for (int j = 0; j < N; j++) {
17 System.out.print(" " + board[i][j] + " ");
18 }
19 System.out.println();
20 }
21 }
22
23 /**
24 * 用于检查是否可以将Queen放在当前位置上
25 *
26 * @param board
27 * @param row
28 * @param col
29 * @return
30 */
31 private boolean isSafe(int[][] board, int row, int col) {
32 int i, j;
33
34 /* 是否在同一行(左侧) */
35 for (i = 0; i < col; i++)
36 if (board[row][i] == 1)
37 return false;
38
39 /* 是否在反对角线方向上 */
40 for (i = row, j = col; i >= 0 && j >= 0; i--, j--)
41 if (board[i][j] == 1)
42 return false;
43
44 /* 是否在对角线方向上 */
45 for (i = row, j = col; j >= 0 && i < N; i++, j--)
46 if (board[i][j] == 1)
47 return false;
48
49 return true;
50 }
51
52 /**
53 * 递归求解N-Queen问题
54 *
55 * @param board
56 * @param col
57 * @return
58 */
59 private boolean solveNQUtils(int[][] board, int col) {
60 /* 如果所有皇后都被放置, 然后返回true */
61 if (col >= N)
62 return true;
63
64 /* 考虑当前col能否摆放Queen */
65 for (int i = 0; i < N; i++) {
66 /* 当前位置是否能摆放Queen */
67 if (isSafe(board, i, col)) {
68 board[i][col] = 1;
69
70 /* 再次摆放Queen, 如果成功直接返回true */
71 if (solveNQUtils(board, col + 1)) {
72 return true;
73 }
74
75 /* 这是在某列无法放Queen回溯时把queen移走 */
76 board[i][col] = 0;
77 }
78 }
79
80 return false;
81 }
82
83 /**
84 * 解决并打印N-Queen的问题
85 *
86 * @return
87 */
88 private boolean solveNQ() {
89 int[][] board = new int[N][N];
90
91 if (!solveNQUtils(board, 0)) {
92 System.out.println("Solution does not exist");
93 return false;
94 }
95
96 printSolution(board);
97 return true;
98 }
99
100 public static void main(String[] args) {
101 NQueenProblem queen = new NQueenProblem();
102 queen.solveNQ();
103 }
104 }

算法:N-皇后问题的更多相关文章

  1. 回溯算法————n皇后、素数串

    回溯就是算法是搜索算法中一种控制策略,是一个逐个试探的过程.在试探的过程中,如果遇到错误的选择,就会回到上一步继续选择下一种走法,一步一步的进行直到找到解或者证明无解为止. 如下是一个经典回溯问题n皇 ...

  2. 算法——八皇后问题(eight queen puzzle)之回溯法求解

    八皇后谜题是经典的一个问题,其解法一共有种! 其定义: 首先定义一个8*8的棋盘 我们有八个皇后在手里,目的是把八个都放在棋盘中 位于皇后的水平和垂直方向的棋格不能有其他皇后 位于皇后的斜对角线上的棋 ...

  3. [算法] N 皇后

    N皇后问题是一个经典的问题,在一个N*N的棋盘上放置N个皇后,每行一个并使其不能互相攻击(同一行.同一列.同一斜线上的皇后都会自动攻击). 一. 求解N皇后问题是算法中回溯法应用的一个经典案例 回溯算 ...

  4. JS算法之八皇后问题(回溯法)

    八皇后这个经典的算法网上有很多种思路,我学习了之后自己实现了一下,现在大概说说我的思路给大家参考一下,也算记录一下,以免以后自己忘了要重新想一遍. 八皇后问题 八皇后问题,是一个古老而著名的问题,是回 ...

  5. 回溯算法 - n 皇后问题

    (1)问题描述 在 n × n 格的棋盘上放置彼此不受攻击的 n 个皇后.按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子.n 后问题等价于在 n × n 的棋盘上放置 n 个 ...

  6. 7, java数据结构和算法: 八皇后问题分析和实现 , 递归回溯

    什么是八皇后问题: 指的是,在一个8 * 8的棋盘中, 放置8个棋子, 保证这8个棋子相互之间, 不在同一行,同一列,同一斜线, 共有多少种摆法? 游戏连接: http://www.4399.com/ ...

  7. noj算法 8皇后打印 回溯法

    描述: 输出8皇后问题所有结果. 输入: 没有输入. 输出: 每个结果第一行是No n:的形式,n表示输出的是第几个结果:下面8行,每行8个字符,‘A’表示皇后,‘.’表示空格.不同的结果中,先输出第 ...

  8. 算法——n皇后问题

    n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击. 给定一个整数 n,返回所有不同的 n 皇后问题的解决方案. 每一种解法包含一个明确的 n 皇后问题的棋 ...

  9. 洛谷 P1219 八皇后【经典DFS,温习搜索】

    P1219 八皇后 题目描述 检查一个如下的6 x 6的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行.每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子. 上面的布局可以用序 ...

  10. 【学习总结】java数据结构和算法-第一章-内容介绍和授课方式

    总目录链接 [学习总结]尚硅谷2019java数据结构和算法 github:javaDSA 目录 几个经典算法面试题 算法和数据结构的重要性 几个经典算法面试题 字符串匹配 暴力法:慢 kmp算法:更 ...

随机推荐

  1. Docker安装GitLab与Runner(网关),常规设置,自动化用到k8s+token

    [转]图文详解k8s自动化持续集成之GitLab CI/CD Windows里面使用Debian命令行工具完成 和Docker网络相关的命令 查看某一个容器的网络 docker inspect 容器I ...

  2. 羽夏看Win系统内核——环境搭建

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...

  3. 双非Java的学习之旅以及秋招路程

    个人信息: 趁着中秋写个帖子记录一下吧.渣渣本,无实习,无高质量证书,走了很多弯路,最后选择的Java后端.现在算是半躺平了,接了几个中小厂的offer保底,20w多的薪资,后面还有几家公司接着面.不 ...

  4. 解决vscode可以编译通过c++项目,但头文件有红色波浪线的问题

    解决vscode可以编译通过c++项目,但头文件有红色波浪线的问题 一.问题描述 我是在Ubuntu 16.04的环境下,用vscode写代码的,一般不使用vscode自带的编译环境,而是用cmake ...

  5. 学习PHP弱引用的知识

    之前的文章中,我们已经学习过引用和引用传值相关的知识.我们知道,PHP 中没有纯引用(指针),不管是对象,还是用引用符号 & 赋值的变量,都是对一个符号表的引用.而今天,我们要学习的是另一种引 ...

  6. javascript 责任链模式 Chain of Responsibility

    * 可拆分的责任链节点 // 可拆分的责任链节点 // Chain.prototype.setNextSuccessor 指定在链条中的下一个节点 // Chain.prototype.passReq ...

  7. javascript DOM 共同父节点

    * 查找两个节点的最近的一个共同父节点,可以包括节点自身 input: oNode1 和 oNode2 在同一文档中,且不会为相同的节点 function commonParentNode(oNode ...

  8. centos 7 & 6 优化脚本

    简单优化 ,未涉及安全优化,如有需求请自行修改脚本实现 1 #!/bin/bash 2 SysVer=`cat /etc/redhat-release | awk -F'release' '{prin ...

  9. 鸿蒙内核源码分析(中断概念篇) | 海公公的日常工作 | 百篇博客分析OpenHarmony源码 | v43.02

    百篇博客系列篇.本篇为: v43.xx 鸿蒙内核源码分析(中断概念篇) | 海公公的日常工作 | 51.c.h .o 硬件架构相关篇为: v22.xx 鸿蒙内核源码分析(汇编基础篇) | CPU在哪里 ...

  10. 02-token

    随着互联网技术的发展,cookie+session形式的用户认真逐渐不适应需求的扩展.在当前分布式微服务广泛流行的场景下,显然这种cookie+session无法满足,因为各个服务之间无法相互获取se ...