递归算法之八皇后问题

article/2025/9/15 9:50:27

        八皇后问题(英文:Eight queens),是由国际象棋棋手马克斯·贝瑟尔于1848年提出的问题,是回溯算法的典型案例。

问题表述为:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。如果经过±90度、±180度旋转,和对角线对称变换的摆法看成一类,共有42类。计算机发明后,有多种计算机语言可以编程解决此问题。

首先是解题的思路:for循环的嵌套  遍历每一种结果

 //依次放入皇后 判断是否冲突for (int i = 0; i < max; i++) {array[n]=i;if (judge(n)){check(n+1);}//如果不冲突就继续执行array[n]=i 即将第n个皇后 放置在本行后移的一个位置}

解题思路详解: 

放置皇后的时候 n=0;直接开始第一次for循环 将一个行的第一个位置放置一个皇后 然后开始第二次for循环 进入第二次for循环的时候n已经+1开始遍历第二行  知道与第一个不冲突 开始第三次for循环 一样的道理 知道第三个与第一个和第二个都不冲突放入 直到放完最后一个 开始回溯 假如中途退出 比如放置第三个的时候每个位置都行不通 就会直接回溯 找出第二个还能放置的位置 在进入遍历第三个 放完一次 回溯到上一位 让上一位换个位置 在进入 让下一位接着遍历每一次 知道前面7个位置所有的方式都遍历完之后 首位才会发生改变  这就是输出结果为什么首位都是按序排列 因为 每一位的每一种可能都考虑到了。

开始的流程图解如下 

回溯的时候差不多大致相同

 

 这里到达顶层了 他会回到皇后7这里 让他后移一位 然后继续回到皇后8 从头遍历看看还有没有合适的解答 假如没有就会回到7 7往后遍历 然后再进8 都没有之后就会进入6 6遍历后移再进7 知道回溯到皇后1 皇后1后移继续开始最开始的流程往上走 走到头再像老样子往后走。

解释完  这里直接放代码了

定义一个输出方法

   /*** 定义一个方法输出每个皇后的位置*/public void print(){count++;for (int i = 0; i < array.length; i++) {System.out.print(array[i]+" ");}System.out.println("");}

然后定义检查是否能放置的方法

    /**** @param n n表示第n+1个皇后 第n+1行的第几个位置*          如array[1] 表示第二行的皇后在第二行的哪个位置* @return 方法是为了确定下一个皇后放在这冲不冲突*/private boolean judge(int n){//i 第i+1个皇后的下标  array[i]表示第i+1行的皇后在哪个位置for (int i = 0; i < n; i++) {//array[i]==array[n] 表示在同一行//重点解释在不在同一斜线的情况  首先要知道达成什么条件在一直线上//这里不卖关子 要知道假如两点连线与水平线形成45度角 在8*8宫格中则在同一直线上//怎么表示两点的夹角 这里Math.abs(n-i)表是行差 Math.abs(array[n]-array[i])表示列差//行差等于列差的时候就代表在一条斜线上 45度夹角 类比正方形if (array[i]==array[n] || Math.abs(n-i) == Math.abs(array[n]-array[i])){return false;}}return true;}

然后放置皇后的方法

    /*** 编写一个方法放置皇后**/public void check(int n){//如果放置完第八个皇后就打印if (n == max){print();return;}//依次放入皇后 判断是否冲突for (int i = 0; i < max; i++) {array[n]=i;if (judge(n)){check(n+1);}//如果不冲突就继续执行array[n]=i 即将第n个皇后 放置在本行后移的一个位置}}

最后主类和运行代码

    static int count = 0;/*** max表示有多少行* 这里用一维数组表示棋牌* 数组的最大容度就是有多少行* 下标+1表示哪行 每个数值表示每行的第几个 就是第几列*/int max = 8;int [] array = new int[max];public static void main(String[] args) {Queen8 queen8 = new Queen8();queen8.check(0);System.out.println(count);}

完整版

package Recursion;/*** @author:LeeGaki* @date:2022/4/26*/
public class Queen8 {static int count = 0;/*** max表示有多少行* 这里用一维数组表示棋牌* 数组的最大容度就是有多少行* 下标+1表示哪行 每个数值表示每行的第几个 就是第几列*/int max = 8;int [] array = new int[max];public static void main(String[] args) {Queen8 queen8 = new Queen8();queen8.check(0);System.out.println(count);}/*** 编写一个方法放置皇后**/public void check(int n){//如果放置完第八个皇后就打印if (n == max){print();return;}//依次放入皇后 判断是否冲突for (int i = 0; i < max; i++) {array[n]=i;if (judge(n)){check(n+1);}//如果不冲突就继续执行array[n]=i 即将第n个皇后 放置在本行后移的一个位置}}/**** @param n n表示第n+1个皇后 第n+1行的第几个位置*          如array[1] 表示第二行的皇后在第二行的哪个位置* @return 方法是为了确定下一个皇后放在这冲不冲突*/private boolean judge(int n){//i 第i+1个皇后的下标  array[i]表示第i+1行的皇后在哪个位置for (int i = 0; i < n; i++) {//array[i]==array[n] 表示在同一行//重点解释在不在同一斜线的情况  首先要知道达成什么条件在一直线上//这里不卖关子 要知道假如两点连线与水平线形成45度角 在8*8宫格中则在同一直线上//怎么表示两点的夹角 这里Math.abs(n-i)表是行差 Math.abs(array[n]-array[i])表示列差//行差等于列差的时候就代表在一条斜线上 45度夹角 类比正方形if (array[i]==array[n] || Math.abs(n-i) == Math.abs(array[n]-array[i])){return false;}}return true;}/*** 定义一个方法输出每个皇后的位置*/public void print(){count++;for (int i = 0; i < array.length; i++) {System.out.print(array[i]+" ");}System.out.println("");}
}

运行结果如下:

 太长了截不全 共92种解就对了。 


http://chatgpt.dhexx.cn/article/ACA2aIcE.shtml

相关文章

八皇后问题4种c语言算法

八皇后问题 1.递归回溯法 B站懒猫老师讲的&#xff08;我在这里学的&#xff09; 八皇后问题的递归回溯算法思路&#xff1a;从第一行开始当某一行皇后位置不与前面所有皇后位置冲突那么记录该行皇后位置并调用递归函数进入下一行&#xff0c;摆放下一个皇后&#xff0c;逐个…

数据结构与算法 — 八皇后问题(回溯算法)

问题描述 在88格的国际象棋上摆放8个皇后&#xff0c;使其不能互相攻击&#xff0c;即任意两个皇后都不能处于同一行、同一列或同一斜线上&#xff0c;问有多少种摆法。 假设上图中红点为一个皇后的位置&#xff0c;那么他的同行&#xff0c;列&#xff0c;斜线上都不能再放置…

数据结构与算法-- 八皇后问题(多种实现方案)

八皇后问题解法一(排列筛选法) 本篇我们承接上一篇中的思想&#xff0c;想到了一个经典的算法题&#xff0c;八皇后问题&#xff1a;题目&#xff1a;在8*8的国际象棋上摆放8个皇后&#xff0c;使得其互相不能攻击&#xff0c;即任意两个换后不能在同一行&#xff0c;同一列&a…

C语言开方问题求助

求助&#xff1a; 使用的是Devcpp进行的编程尝试 在写程序的时候遇到了个问题&#xff0c;运行后结果显示为1#j 后来在朋友的帮助下改正了程序&#xff0c;解决了错误。之后的话&#xff0c;我按照我朋友的改正过的程序自己再重新打了一遍&#xff0c;结果运行后的结果还是显示…

C语言笔记

目录 基础... 3 基本类型数据... 5 定义变量... 6 进制... 6 ASCII&#xff08;阿斯克码&#xff09;... 7 输入输出... 8 printf&#xff08;&#xff09;将变量的内容输出到显示器上... 8 scanf &#xff08;&#xff09;[通过键盘将数据输入到变量中] 9 运算符... …

c语言 大数开方,大数加法之C语言函数法(只有正数版)

由于某些原因&#xff0c;我于今天2017-4-19将我的博文搬到博客园了&#xff0c;以后我就在这里扎根了。 之前想过在博客写文章方便日后复习&#xff0c;但一直未能实现&#xff0c;所以&#xff0c;现在这篇是我个人人生中第一篇博客&#xff0c;所以写博客完全没经验&#xf…

开平方的快速算法(C代码)

目录&#xff1a; 一、牛顿迭代法 二、采用移位、加减法、判断和循环实现开平方 三、效率远高于牛顿迭代法开平方法 1、原理 2、实现代码 四、卡马克快速开平方算法(推荐) 1、C-Free模拟验证卡马克开平方 2、移植到实际的项目 3、卡马克快速开平方的由来 1&#xff0…

windows 区域截屏以及延迟截屏

提起在Windows&#xff0c; 我们都会用到截屏功能&#xff0c;今天论述一下window 10系统自带的截图应用Snipping Tool 打开Snipping Tool 找到任务栏下的放大镜图标&#xff0c;点击 在下方输入snipping&#xff0c;会在左侧找到截图软件Snipping Tool&#xff0c;点击可进入…

小米手机解决此区域不可截屏

小米手机解决此区域不可截屏 无意中暂停视频弹出消息&#xff0c;想试试可不可以截屏竟然可以截屏&#xff0c;但是视频一播放就截屏不了了&#xff0c;录屏也是&#xff0c;直接变黑或者是直接提示弹窗&#xff0c;嘻嘻嘻嘻小米bug还是有好处滴

浏览器网页截屏实用小技巧

浏览器开发者工具中自带的截屏太方便了&#xff01; 打开开发者工具&#xff0c;输入 ctrl shift P 快捷键&#xff0c;输入screenshot&#xff0c;出现了四个选项&#xff0c;分别是&#xff1a; 1.area screenshot - 区域截图 2.full size screenshot - 对浏览器所有内容…

如何利用计算机截屏快捷键,电脑怎么截图 电脑选区域截图怎么截 电脑截图快捷键是什么...

电脑怎么截图 按照操作上从易到难的顺序&#xff0c;给你推荐五种截屏方式 &#xff1a; 第一种&#xff1a;Ctrl PrScrn 使用这个组合键截屏&#xff0c;获得的是整个屏幕的图片; 第二种&#xff1a;Alt PrScrn 这个组合键截屏&#xff0c;获得的结果是 当前窗口的图片; 第三…

iOS 截屏指定区域

转自&#xff1a;链接&#xff1a;https://www.jianshu.com/p/39db0fa66c0e 指定截屏代码实现 全屏截图效果 全屏截图效果 指定区域截屏效果 指定区域截屏效果 这里先上代码&#xff0c;代码后面有相关方法的解释第一种方法代码下载 /**创建一个基于位图的上下文&#xff0…

windows如何截屏

截屏是我们平时工作或记录常用的操作&#xff0c;不过有人不知道怎么用系统截屏&#xff0c;今天&#xff0c;小编带来了系统的几种截屏&#xff0c;让我们来看看吧&#xff01; 一、快捷键截图 1. Win shift S&#xff1a;可以选择截图区域的大小&#xff0c;CtrlV粘贴在w…

Android 任意区域截屏

1、全屏截图 Android其实可以做到任意区域截屏&#xff0c;不过我们先来看看整个屏幕截图代码&#xff0c;相信大家很熟悉&#xff0c;代码如下 View decorView activity.getWindow().getDecorView(); decorView.setDrawingCacheEnabled(true); view.buildDrawingCache(); /…

snipaste 固定位置截屏

原文参考&#xff1a; snipaste怎么固定位置截图&#xff0c;如何统一大小截图 一、电脑点击【snipaste】&#xff0c;或者点击键盘的“F1”。 二、在图片&#xff0c;根据自己的需求&#xff0c;画出截图的位置和大小&#xff0c;比如&#xff1a;本篇是500*296。 三、点击右…

JavaScript实现浏览器特定区域截屏和下载功能

JavaScript实现浏览器特定区域截屏功能 需求介绍尝试一&#xff1a;使用Jtopo.js自带的保存图片方法&#xff08;不能对资源进行下载&#xff09;尝试二&#xff1a;对saveImageInfo进行改写&#xff08;功能能用&#xff0c;但是会因为跨域问题污染canvas&#xff09;&#xf…

Unity中的截图方法(包括全屏截图、区域截图、Camera截图和摄像头截图)

Unity中的截图方法&#xff08;包括全屏截图、区域截图、Camera截图和摄像头截图&#xff09; Application.CaptureScreenshotScreenCapture Texture2D.ReadPixels视口截图RenderTexture&#xff08;Camera截图&#xff09;WebCamTexture&#xff08;摄像头截图、照相&#xff…

实现区域截图功能

利用QQ或微信自带的截图功能实现区域截图。 在腾讯安装目录下找到PrScrn.dll&#xff0c;并将它放在需要的位置&#xff0c; 将D:/PrScrn.dll修改为你的目录。 如果在maya里面直接使用该代码 import os,subprocess from PySide2.QtWidgets import QApplication clipboard …

小米手机怎么截屏?小米手机区域截屏

小米手机怎么截屏&#xff1f;手机的截屏其实都是差不多的&#xff0c;基本上都是三指向下滑动而达到截屏效果的&#xff0c;但基本都是全屏截图。小米手机区域截屏怎么做&#xff1f;如果想要做到任意位置的那种区域块截屏的话&#xff0c;该怎么做&#xff1f;下面就来看看吧…

浏览器截图方法(长截图、node截图、指定区域截图)

1.打开需要截屏的页面&#xff0c;按键盘上的F2&#xff08;或者CtrlShiftI&#xff09;打开浏览器控制台 2.CtrlshiftP进入搜索框&#xff0c;输入“screen”: 这里有四种截图模式&#xff0c;点击需要的截图方式即可截取图片。