一文搞懂数据结构之 递归-八皇后问题
2021/8/6 23:09:43
本文主要是介绍一文搞懂数据结构之 递归-八皇后问题,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
八皇后是一个经典的递归问题,为了加深对八皇后解题思路的理解,故写此笔记
首先,了解一下八皇后问题:
八皇后问题(英文:Eight queens),是由国际西洋棋棋手马克斯·贝瑟尔于1848年提出的问题,是回溯算法的典型案例。 问题表述为:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
根据八皇后问题提取八皇后摆放条件
1. 任意皇后不能在同一列
2.任意皇后不能在同一行
3. 任意皇后不能在同一斜线
画图理解:
肉眼观察,在同一行,同一列的好判断,那么在同一斜线上的怎么判断呢,这里再来看一个图
可以看到,蓝皇后和绿皇后在同一斜线上,和红皇后也在同一斜线上,
通过观察,可以发现,蓝皇后到绿皇后的横向距离和纵向距离相等,都是3 ,而到红皇后的横纵距离也相等是1。不难发现,蓝皇后到到红绿皇后的横纵距离分别相等,而那条斜线,他的斜率是1 或-1,根据计算蓝皇后和每个皇后的斜率,只要不是1 或-1 再加上条件 不在同一行,同一列,我们就可以知道这个皇后的摆放位置是否符合规则。
总结条件:【1. 不在同一行 | 2. 不在同一列 | 3. 和已放置的皇后的斜率不等一 1 或 -1 即 绝对值不等一1 】
整个回溯求解过程中,最难理解的可能就是皇后的斜边冲突问题。
求解约定:
定义一个一维数组去作为棋盘
一维数组的下标是棋盘的行,一维数组的值表示皇后放在该行的第几列
假如 arr[0] = 0 下标是0 值是 0 就是棋盘的第1行,第一列,就是第1个黑皇后的位置
假如 arr[1] = 2 下标是1 值是 2 就是棋盘的第2行,第3列 ,就是第2个绿皇后的位置
假如 arr[3] = 6 下标是3 值是 6 就是棋盘的第4行,第7列 ,就是第4个红皇后的位置
.......
那么,判断第 n 和皇后位置摆放是否符合规则的条件就是
第 n 个皇后所在的列和已放置的皇后不在同一列, arr[i] != arr[n] i 取值 [0,n)
第 n 个皇后和已放置皇后的横向距离 != 纵向距离 即 (n-i) != | arr[n] - arr[i] |
(n-i) 是纵向距离,即隔了多少行,
而,arr[n] 是第n 个皇后所在的列,arr[i] 是第 i 个皇后所在的列
所以 | arr[n] - arr[i] | 即第n个皇后 和第 i 个皇后的列距离的绝对值
求解八皇后代码:注释很全
package pers.uxteam.data; /* * 约定: 用一个一维数组表示八皇后棋盘, * 八皇后棋盘一共 8 行 8 列 范围是[0,7] * 那么,一维数组的下表表示棋盘的行, * 一维数组的值表示皇后所在的列 取值范围 [0,7] * 例如 :int[] map = [4, 2, 0, 5, 7, 1, 3, 6] * map[0] = 4 // 表示在棋盘的第 0 行,第 4 列 是第一个皇后的摆放位置 * map[1] = 2 // 表示在棋盘的第 1 行,第 2 列 是第一个皇后的摆放位置 * map[3] = 0 // 表示在棋盘的第 3 行,第 0 列 是第一个皇后的摆放位置 * ....... * [0, 0, 0, 0, 1, 0, 0, 0] [0, 0, 1, 0, 0, 0, 0, 0] [1, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 1, 0] [0, 1, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 1] [0, 0, 0, 0, 0, 1, 0, 0] [0, 0, 0, 1, 0, 0, 0, 0] * */ import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class Queue8 { private int max = 8; // 定义八行八列 private int[] chess = new int[max]; // 放置第 n 个皇后 public void layon(int n){ // 如果放到了第 max 个皇后,就结束迭代 if (n == max){ // 可以打印 chess 观察皇后摆放 show(); return; } // 放置 n 个皇后 for (int i = 0; i < max; i++){ // 这个循环的意义是,皇后放在第 i 列是否合适 chess[n] = i; // 放到这一列 if (isRight(n)){ // 检测放到这一列,皇位是否安稳 // 如果可以,就继续迭代,去放 下一个皇后 n + 1 layon(n+1); } // 否则继续循环,放置到其他列 } } // 判断第n个皇后的位置是否和其他皇后冲突 public boolean isRight(int n){ // 根据约定,我们知道,在摆放第 n 个皇后时,不能和其他皇后在同一列, // 也就是数组的值不相同,这是第一个条件 // 每个皇后都不能在同一斜线上,也就是皇后到皇后之间的行和列距离不能相等, // 不然就是正方形,,那么这条斜线的斜率要么是1,要么是-1 可以使用绝对值化, // 判断行列距离是否相等。 // 和前面 的皇后比较是否冲突,当我们摆放 第 n 个皇后时,前面已经有了 n -1 个皇后 // 每个都要判断 for (int i = 0;i<n;i++){ if (chess[i] == chess[n] || Math.abs(n-i) == Math.abs(chess[n] - chess[i])){ // 冲突 return false; } } return true; } public void show(){ int[][] chess = new int[max][max]; // 将一维数组恢复成二维数组打印 for (int i = 0; i< max; i++){ chess[i][this.chess[i]] = 1; } for (int[] row : chess){ // 打印每一行 List<Integer> collect = Arrays.stream(row).boxed().collect(Collectors.toList()); System.out.println(collect); } } }
这篇关于一文搞懂数据结构之 递归-八皇后问题的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南