算法:N-皇后问题
一、八皇后问题
八皇后问题是一个以国际象棋为背景的问题:如何能够在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-皇后问题的更多相关文章
- 回溯算法————n皇后、素数串
回溯就是算法是搜索算法中一种控制策略,是一个逐个试探的过程.在试探的过程中,如果遇到错误的选择,就会回到上一步继续选择下一种走法,一步一步的进行直到找到解或者证明无解为止. 如下是一个经典回溯问题n皇 ...
- 算法——八皇后问题(eight queen puzzle)之回溯法求解
八皇后谜题是经典的一个问题,其解法一共有种! 其定义: 首先定义一个8*8的棋盘 我们有八个皇后在手里,目的是把八个都放在棋盘中 位于皇后的水平和垂直方向的棋格不能有其他皇后 位于皇后的斜对角线上的棋 ...
- [算法] N 皇后
N皇后问题是一个经典的问题,在一个N*N的棋盘上放置N个皇后,每行一个并使其不能互相攻击(同一行.同一列.同一斜线上的皇后都会自动攻击). 一. 求解N皇后问题是算法中回溯法应用的一个经典案例 回溯算 ...
- JS算法之八皇后问题(回溯法)
八皇后这个经典的算法网上有很多种思路,我学习了之后自己实现了一下,现在大概说说我的思路给大家参考一下,也算记录一下,以免以后自己忘了要重新想一遍. 八皇后问题 八皇后问题,是一个古老而著名的问题,是回 ...
- 回溯算法 - n 皇后问题
(1)问题描述 在 n × n 格的棋盘上放置彼此不受攻击的 n 个皇后.按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子.n 后问题等价于在 n × n 的棋盘上放置 n 个 ...
- 7, java数据结构和算法: 八皇后问题分析和实现 , 递归回溯
什么是八皇后问题: 指的是,在一个8 * 8的棋盘中, 放置8个棋子, 保证这8个棋子相互之间, 不在同一行,同一列,同一斜线, 共有多少种摆法? 游戏连接: http://www.4399.com/ ...
- noj算法 8皇后打印 回溯法
描述: 输出8皇后问题所有结果. 输入: 没有输入. 输出: 每个结果第一行是No n:的形式,n表示输出的是第几个结果:下面8行,每行8个字符,‘A’表示皇后,‘.’表示空格.不同的结果中,先输出第 ...
- 算法——n皇后问题
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击. 给定一个整数 n,返回所有不同的 n 皇后问题的解决方案. 每一种解法包含一个明确的 n 皇后问题的棋 ...
- 洛谷 P1219 八皇后【经典DFS,温习搜索】
P1219 八皇后 题目描述 检查一个如下的6 x 6的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行.每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子. 上面的布局可以用序 ...
- 【学习总结】java数据结构和算法-第一章-内容介绍和授课方式
总目录链接 [学习总结]尚硅谷2019java数据结构和算法 github:javaDSA 目录 几个经典算法面试题 算法和数据结构的重要性 几个经典算法面试题 字符串匹配 暴力法:慢 kmp算法:更 ...
随机推荐
- 【转】shell脚本中echo显示内容带颜色的实现方法
shell脚本中echo显示内容带颜色的实现方法 shell脚本里使用echo输出颜色
- uni-app仿抖音APP短视频+直播+聊天实例|uniapp全屏滑动小视频+直播
基于uniapp+uView-ui跨端H5+小程序+APP短视频|直播项目uni-ttLive. uni-ttLive一款全新基于uni-app技术开发的仿制抖音/快手短视频直播项目.支持全屏丝滑般上 ...
- 第一次用AngularJS
1.创建指令的4种方式(ECMA) var appModule = angular.module('app', []); appModule.directive('hello', function() ...
- EditPlus配置C/C++运行环境
1.安装MinGW和EditPlus 2.打开EditPlus ctrl+1 编译 ctrl+2 运行
- Java实现导入Excel文件
一.配置文件名称.路径.内容: <bean id="multipartResolver" class="org.springframework.web.multip ...
- disruptor笔记之三:环形队列的基础操作(不用Disruptor类)
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- html table 固定列
css固定列: .td1{ position: sticky; z-index: 1; left:0; }
- Python就业方向
0.WEB开发 Python拥有很多免费数据函数库.免费web网页模板系统.以及与web服务器进行交互的库,可以实现web开发,搭建web框架,目前比较有名气的Python web框架为Django. ...
- Python生成桌面应用
1.cd进入project所在根目录 2.pyinstaller -F demo.py --noconsole 3.自定义图标 选择ico格式图标发在project目录 4.pyinstaller - ...
- 定要过python二级 选择题第四套
1. 2. 3. 4. 5. 6. python用于人工智能 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.