八皇后问题的研究分析解决《Blind-Stab》

2023-10-18 18:20

本文主要是介绍八皇后问题的研究分析解决《Blind-Stab》,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目:

八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种计算机语言可以解决此问题。

如图其中一种可能性:

分析:

1,所谓八皇后,就是找可能性。8x8大小的棋盘,放8个棋子,每个棋子的横列斜三个方向都只能有它一个存在。

2,很明显我们应该定义一个二位数组模拟棋盘,初始化这个二维数组的值全部为0,刚好我们把0当作未放棋子的状态。

3,每当我们放一个棋子,我们就把放置棋子处的值变成1,代表放置了一个皇后。

4,我们写一个方法findQueen(int row,int [ ] [ ] arr),来放置棋子,参数row代表当前要放的行,二维数组代表棋盘。

5,一开始我们准备放置第一个棋子,传入该方法的参数row应该为0,代表第一行。

6,这个方法该怎么实现呢,我们准备递归调用这个方法。我们找出归的条件  if(row == 8)

7,当row == 8的时候,也就是我们准备放第9个棋子,也就是说符合条件的8个棋子都放好了,那我们打印就行了。

8,但是当row不等于或者说小于8的时候呢?也就是还没放完的情况呢,也就是每次我们该怎么放第row + 1行呢?

9,一开始传递进来的row是为0的,代表着从第一行开始放,既然我们归的条件已经写好了,我们就来写递的情况。

10,第一行,row == 0,一个棋子都还没放,我们是不是应该找位置,找可以放的地方,怎么找,行是确定的。

11,我们肯定是遍历列啊,就是第1行的哪一列可以放棋子呢,遍历,从第1列开始,到最后一列,找到了可以放的地方就直接放

12,放下去之后我们就不用管了,接下来就找第二行,那我们就直接调用findQueen(row + 1,arr),我们先假设我们第一行放的位置没有问题,让他去找第二行,同理,找到了第二行他会去找第三行,,,

13,但是,这样下去一开始没问题,但可能到了第5,或者第6行的时候,他会发现它遍历了所有列,却发现哪一列都不能放。

14,那怎么办呢?不要怕,我们写的是递归啊,它遍历完所有的列都不行那说明他的前一行放错了,应该放下一个位置试试

15,因为它一个都没有找到,他就从那个递归中出来了,因为我们下面什么都没写。他就回到了上一层

16,我们说过是它上一层放的位置不对,不对那就换,移动,上一层的for循环还在呢还没完,i++了

17,但是,在这之前,你得做一件事,你上一层放的位置不对,但是它还是放了,所以你得清空那个不对的位置。

18,而我们传递进下一行的参数一直都是row + 1,也就是说它的上一层还在原来的位置,不能放,我就先清空,arr[row][j] = 0;

19,让他重新为0,才j++,也就是下一列看看能不能放。

20,至此,这个递归调用就完整了。

 

下面来看看我的源代码:

public class EightQueenT {public static int counts = 0;public static void main(String[] args) {//定义8*8大小的二维数组模拟棋盘//初始化值皆为0int [][] arr = new int[8][8];findQueen(0,arr);}public static void findQueen(int row, int[][] arr) {//我们对当前行进行判断//row == 8说明8行皇后打印完毕,一种情况出来,直接打印if(row == 8) {counts++;//对情况进行统计,看看情况总数对不System.out.println("第" + counts + "种情况");for (int i = 0; i < arr.length; i++) {for (int j = 0; j < arr.length; j++) {System.out.print(arr[i][j] + " ");}System.out.println("");//换行控制格式}}else {//如果没有放完8个,我们继续找//行是确定的,我们找列,看看哪一列可以放for (int col = 0; col < arr.length; col++) {//如果此处此行此列没有危险,能放if(!Danger(row,col,arr)) {//那就放,将此处的值变为1arr[row][col] = 1;//并且递归调用方法,参数变为下一行findQueen(row + 1,arr);//但是要是这一行一个都没有//那说明我上一行的列放错了//那我就要将放错的这个位置请0arr[row][col] = 0;}}}}//此方法判断我准备放的位置有没有危险public static boolean Danger(int row, int col, int[][] arr) {//判断八个方向,但是因为是一层一层放的下面都还没放,所以下面肯定不会相同//左边不行都被我清空过,右边都还没放,所以不必判断//那我就只要判断左上,上,右上//往上//当前列不变,行从当前行-1判断至第一行for (int r = row - 1; r >= 0; r--) {//看看上方有没有==1的,也就是有没有皇后if(arr[r][col] == 1) {//有的话直接返回true,表示有危险不能放return true;}}//左上//当前位置行和列都-1开始,每次减一,但是要判断到棋盘边界则停止for (int r = row - 1,c = col - 1; r >= 0&&c >= 0; r--,c--) {//看看左上方有没有==1的,也就是有没有皇后if(arr[r][c] == 1) {//有的话直接返回true,表示有危险不能放return true;}}//右上//当前行从-1开始,列从+1开始,行每次行--,列++//行边界大于等于0,列到arr.length - 1for (int r = row - 1,c = col + 1; r >= 0&&c <= arr.length - 1; r--,c++) {//看看左上方有没有==1的,也就是有没有皇后if(arr[r][c] == 1) {//有的话直接返回true,表示有危险不能放return true;}}//如果这三种情况都没有,代表没有危险可以放返回falsereturn false;}}

运行结果如下:

总结:

其实就是判断,能放就放,不能放就下一列。当前行的所有列都不能放就回溯。

用程序来模拟思维,一定要思路清晰,想好所有情况。

 

 

 

 

 

 

 

 

 

 

这篇关于八皇后问题的研究分析解决《Blind-Stab》的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/234349

相关文章

MybatisGenerator文件生成不出对应文件的问题

《MybatisGenerator文件生成不出对应文件的问题》本文介绍了使用MybatisGenerator生成文件时遇到的问题及解决方法,主要步骤包括检查目标表是否存在、是否能连接到数据库、配置生成... 目录MyBATisGenerator 文件生成不出对应文件先在项目结构里引入“targetProje

C#使用HttpClient进行Post请求出现超时问题的解决及优化

《C#使用HttpClient进行Post请求出现超时问题的解决及优化》最近我的控制台程序发现有时候总是出现请求超时等问题,通常好几分钟最多只有3-4个请求,在使用apipost发现并发10个5分钟也... 目录优化结论单例HttpClient连接池耗尽和并发并发异步最终优化后优化结论我直接上优化结论吧,

Java内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J

numpy求解线性代数相关问题

《numpy求解线性代数相关问题》本文主要介绍了numpy求解线性代数相关问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 在numpy中有numpy.array类型和numpy.mat类型,前者是数组类型,后者是矩阵类型。数组

解决systemctl reload nginx重启Nginx服务报错:Job for nginx.service invalid问题

《解决systemctlreloadnginx重启Nginx服务报错:Jobfornginx.serviceinvalid问题》文章描述了通过`systemctlstatusnginx.se... 目录systemctl reload nginx重启Nginx服务报错:Job for nginx.javas

Redis主从/哨兵机制原理分析

《Redis主从/哨兵机制原理分析》本文介绍了Redis的主从复制和哨兵机制,主从复制实现了数据的热备份和负载均衡,而哨兵机制可以监控Redis集群,实现自动故障转移,哨兵机制通过监控、下线、选举和故... 目录一、主从复制1.1 什么是主从复制1.2 主从复制的作用1.3 主从复制原理1.3.1 全量复制

Redis缓存问题与缓存更新机制详解

《Redis缓存问题与缓存更新机制详解》本文主要介绍了缓存问题及其解决方案,包括缓存穿透、缓存击穿、缓存雪崩等问题的成因以及相应的预防和解决方法,同时,还详细探讨了缓存更新机制,包括不同情况下的缓存更... 目录一、缓存问题1.1 缓存穿透1.1.1 问题来源1.1.2 解决方案1.2 缓存击穿1.2.1

Mysql DATETIME 毫秒坑的解决

《MysqlDATETIME毫秒坑的解决》本文主要介绍了MysqlDATETIME毫秒坑的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 今天写代码突发一个诡异的 bug,代码逻辑大概如下。1. 新增退款单记录boolean save = s

vue解决子组件样式覆盖问题scoped deep

《vue解决子组件样式覆盖问题scopeddeep》文章主要介绍了在Vue项目中处理全局样式和局部样式的方法,包括使用scoped属性和深度选择器(/deep/)来覆盖子组件的样式,作者建议所有组件... 目录前言scoped分析deep分析使用总结所有组件必须加scoped父组件覆盖子组件使用deep前言

解决Cron定时任务中Pytest脚本无法发送邮件的问题

《解决Cron定时任务中Pytest脚本无法发送邮件的问题》文章探讨解决在Cron定时任务中运行Pytest脚本时邮件发送失败的问题,先优化环境变量,再检查Pytest邮件配置,接着配置文件确保SMT... 目录引言1. 环境变量优化:确保Cron任务可以正确执行解决方案:1.1. 创建一个脚本1.2. 修