Java使用递归回溯完美解决八皇后的问题

Java使用递归回溯完美解决八皇后问题

什么是八皇后问题

八皇后是一个以棋盘为底盘,放置八个皇后的问题,皇后拥有垂直、水平和对角线的移动能力,要求任意两个皇后都不能在同一行、同一列或同一对角线上。

解题思路

因为任意两个皇后不能在同一行、同一列或同一对角线上,因此我们可以通过递归回溯的思路,按行对皇后进行放置,逐步约束各个皇后的位置,以达到放置成功且不冲突的状态。

具体步骤如下:

  1. 初始化棋盘,用 0 表示空格,1 表示皇后。
  2. 从棋盘第一行开始,按照列的顺序依次尝试放置皇后。
  3. 当尝试放置皇后时,判断该位置是否与之前已经放置的皇后位置产生冲突。如果产生冲突,继续尝试下一列;如果不产生冲突,将皇后放在该位置,并标记此位置为 1。
  4. 继续按行进行递归,直到放置第 8 个皇后或者无法继续放置。如果无法继续放置,则回溯到上一个皇后位置进行重新尝试,直到找到不冲突的位置或者所有位置都尝试过了。

代码实现

我们可以使用一个一维数组 int[] queen 来表示各个皇后的位置。queen[i] 表示第 i 行的皇后所在的列数。在每个节点进行选择时,我们需要将当前皇后所有可能的放置位置进行遍历,并进行回溯。

示例代码:

class EightQueens {
    private int[] queen = new int[8];    // 记录每个皇后的位置,初始化都为 0
    private int count = 0;    // 记录解法的数量
    private void placeQueen(int row) {
        // 递归终止条件:如果 row == 8,说明 8 个皇后已经全部放置成功,此时将当前棋盘打印出来
        if (row == 8) {
            printQueen();
            count++;
            return;
        }
        // 尝试放置第 row 行皇后
        for (int col = 0; col < 8; col++) {
            if (check(row, col)) {  // 判断该位置是否冲突
                queen[row] = col;   // 如果不冲突,则将皇后放在该位置
                placeQueen(row + 1);    // 继续放置下一行的皇后
            }
        }
    }
    // 判断放置在 (row, col) 位置的皇后是否与之前的皇后冲突
    private boolean check(int row, int col) {
        for (int i = 0; i < row; i++) {
            // 如果同一列已经有皇后,或者斜方向上的两个点距离相等,则说明冲突
            if (queen[i] == col || Math.abs(row - i) == Math.abs(col - queen[i])) {
                return false;
            }
        }
        return true;
    }
    // 打印棋盘
    private void printQueen() {
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                if (queen[i] == j) {
                    System.out.print("1 ");
                } else {
                    System.out.print("0 ");
                }
            }
            System.out.println();
        }
        System.out.println();
    }
    public void solve() {
        placeQueen(0);
        System.out.println("共有 " + count + " 种解法");
    }
}

我们创建一个 EightQueens 的实例,并调用 solve() 方法,即可解决八皇后问题并输出所有解法的情况。下面是一个示例:

EightQueens eightQueens = new EightQueens();
eightQueens.solve();

输出:

0 0 0 0 1 0 0 0 
0 0 0 0 0 0 0 1 
0 0 0 1 0 0 0 0 
0 0 0 0 0 0 1 0 
1 0 0 0 0 0 0 0 
0 0 1 0 0 0 0 0 
0 0 0 0 0 1 0 0 
0 1 0 0 0 0 0 0 

0 0 0 0 0 1 0 0 
0 0 0 0 0 0 0 1 
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 0 0 1 0 0 0 0 
0 1 0 0 0 0 0 0 

共有 92 种解法

可以发现,八皇后问题共有 92 种解法。

示例说明

示例一

我们假设在八皇后问题中,求取其中一种解法。此时,我们可以使用回溯算法,从第一行开始,逐个尝试每个皇后的位置。如果该位置不与之前的皇后产生冲突,则将该皇后放置在该位置,继续放置下一行的皇后。如果当前皇后无论在哪个位置都无法放置成功,则回溯到上一个皇后位置重新放置。

代码实现如下:

class EightQueens {
    private int[] queen = new int[8];    // 记录每个皇后的位置,初始化都为 0
    public void solve() {
        placeQueen(0);
    }
    private void placeQueen(int row) {
        // 如果 8 个皇后都放置成功,打印棋盘并返回
        if (row == 8) {
            printQueen();
            return;
        }
        // 尝试把皇后放在当前行的每一列上,并递归尝试下一行的放置
        for (int col = 0; col < 8; col++) {
            if (check(row, col)) {  // 判断当前位置是否可以放置
                queen[row] = col;   // 如果可以,将皇后放置在该位置
                placeQueen(row + 1);    // 放置下一行的皇后
            }
        }
    }
    // 判断放置在 (row, col) 位置的皇后是否与之前的皇后冲突
    private boolean check(int row, int col) {
        for (int i = 0; i < row; i++) {
            // 如果同一列已经有皇后,或者斜方向上的两个点距离相等,则说明冲突
            if (queen[i] == col || Math.abs(row - i) == Math.abs(col - queen[i])) {
                return false;
            }
        }
        return true;
    }
    // 打印棋盘
    private void printQueen() {
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                if (queen[i] == j) {
                    System.out.print("1 ");
                } else {
                    System.out.print("0 ");
                }
            }
            System.out.println();
        }
        System.out.println();
    }
}

EightQueens eightQueens = new EightQueens();
eightQueens.solve();

输出:

0 0 0 0 1 0 0 0 
0 0 0 0 0 0 0 1 
0 0 0 1 0 0 0 0 
0 0 0 0 0 0 1 0 
1 0 0 0 0 0 0 0 
0 0 1 0 0 0 0 0 
0 0 0 0 0 1 0 0 
0 1 0 0 0 0 0 0 

这一种解法中,所有皇后的位置分别为 (0, 4), (1, 7), (2, 3), (3, 6), (4, 0), (5, 2), (6, 5), (7, 1)

示例二

我们假设在八皇后问题中,求取所有解法,代码实现如下:

class EightQueens {
    private int[] queen = new int[8];    // 记录每个皇后的位置,初始化都为 0
    private int count = 0;    // 记录解法的数量
    private void placeQueen(int row) {
        // 递归终止条件:如果 row == 8,说明 8 个皇后已经全部放置成功,此时将当前棋盘打印出来
        if (row == 8) {
            printQueen();
            count++;
            return;
        }
        // 尝试放置第 row 行皇后
        for (int col = 0; col < 8; col++) {
            if (check(row, col)) {  // 判断该位置是否冲突
                queen[row] = col;   // 如果不冲突,则将皇后放在该位置
                placeQueen(row + 1);    // 继续放置下一行的皇后
            }
        }
    }
    // 判断放置在 (row, col) 位置的皇后是否与之前的皇后冲突
    private boolean check(int row, int col) {
        for (int i = 0; i < row; i++) {
            // 如果同一列已经有皇后,或者斜方向上的两个点距离相等,则说明冲突
            if (queen[i] == col || Math.abs(row - i) == Math.abs(col - queen[i])) {
                return false;
            }
        }
        return true;
    }
    // 打印棋盘
    private void printQueen() {
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                if (queen[i] == j) {
                    System.out.print("1 ");
                } else {
                    System.out.print("0 ");
                }
            }
            System.out.println();
        }
        System.out.println();
    }
    public void solve() {
        placeQueen(0);
        System.out.println("共有 " + count + " 种解法");
    }
}

EightQueens eightQueens = new EightQueens();
eightQueens.solve();

输出:

0 0 0 0 1 0 0 0 
0 0 0 0 0 0 0 1 
0 0 0 1 0 0 0 0 
0 0 0 0 0 0 1 0 
1 0 0 0 0 0 0 0 
0 0 1 0 0 0 0 0 
0 0 0 0 0 1 0 0 
0 1 0 0 0 0 0 0 

0 0 0 0 0 1 0 0 
0 0 0 0 0 0 0 1 
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 0 0 1 0 0 0 0 
0 1 0 0 0 0 0 0 

...
共有 92 种解法

可以发现,八皇后问题共有 92 种解法。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java使用递归回溯完美解决八皇后的问题 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • 华为nova2和荣耀9哪个值得买?华为荣耀9和华为nova2全面深度区别对比评测图解

    华为nova2和荣耀9哪个值得买? 华为nova2和荣耀9都是华为公司推出的高性能智能手机,它们在外观、性能、摄影等方面有一些区别。下面将详细介绍它们的特点和优劣,以帮助您做出购买决策。 外观设计 华为nova2采用了全金属机身设计,具有简洁、时尚的外观。它的边框非常窄,屏占比较高,给人一种大屏幕的视觉效果。荣耀9则采用了玻璃机身设计,给人一种更加光滑、精致…

    other 2023年8月2日
    00
  • numpy库的下载及安装(吐血总结)

    numpy库的下载及安装(吐血总结) NumPy是Python中用于科学计算的重要库之一,该库提供了大量高级的数值编程工具,适用于任何需要进行数据处理和分析的应用场景。但是,有时候刚刚学习Python的初学者可能会对NumPy的下载和安装过程感到困惑。本文将在吐血总结的基础上,为需要安装NumPy库的读者提供一些帮助。 下载NumPy库 NumPy库最简单的…

    其他 2023年3月29日
    00
  • Android DrawerLayout布局与NavigationView导航菜单应用

    Android DrawerLayout布局与NavigationView导航菜单应用攻略 1. 简介 DrawerLayout布局与NavigationView导航菜单是Android开发中常用的组件,用于实现侧滑菜单和导航功能。DrawerLayout是一个容器布局,可以包含两个子视图,一个主视图和一个抽屉视图。NavigationView是一个导航菜单…

    other 2023年8月24日
    00
  • Android 滑动Scrollview标题栏渐变效果(仿京东toolbar)

    Android 滑动ScrollView标题栏渐变效果(仿京东toolbar)攻略 简介 在这个攻略中,我们将学习如何实现一个滑动ScrollView时标题栏渐变的效果,类似于京东App中的toolbar。这个效果可以提升用户体验,使得界面更加流畅和美观。 步骤 步骤一:准备工作 首先,我们需要在Android项目中创建一个新的Activity或Fragme…

    other 2023年8月25日
    00
  • IOS使用TestFlight测试的使用方法

    下面我将为你详细讲解 iOS 使用 TestFlight 测试的使用方法。 什么是 TestFlight TestFlight 是一个由苹果公司提供的用于 iOS 应用的 beta 测试平台。通过 TestFlight,开发者可以将应用测试版本发送给测试者,让他们在测试版中使用和体验应用,测试者还可以向开发者提供反馈和 bug 报告。TestFlight 有…

    other 2023年6月28日
    00
  • Python如何telnet到网络设备

    当需要通过python来管理网络设备时,可以使用telnet库来建立到设备的telnet连接。下面是Python如何telnet到网络设备的完整攻略: 1. 安装telnet库 首先需要安装Python的telnet库。如果你使用的是Python 2.x版本,那么telnet库已经默认安装。如果你使用的是Python 3.x版本,可以使用下面的pip命令来安…

    other 2023年6月27日
    00
  • Unix系统中常用内置工具的命令使用指南

    针对“Unix系统中常用内置工具的命令使用指南”的完整攻略,我来为您进行详细讲解。 一、命令行介绍 在 Unix 系统中,用户可以通过终端窗口使用命令行来完成各种操作。使用命令行的优势在于可以快速高效地进行各种操作。以下是一些常用的命令行基础: cd 命令用于进入指定目录,如 cd /home 进入 home 目录。 ls 命令用于列出当前目录下的文件和文件…

    other 2023年6月26日
    00
  • win10系统32位怎么升64位系统?win10系统32位升64位系统操作教程

    升级操作系统的过程是比较复杂的,需要一定的技术知识和操作经验。在升级前,请务必备份重要的文件和数据,以防数据丢失。以下是升级Win10 32位系统到64位系统的详细攻略: 步骤1:检查硬件兼容性首先,你需要确认你的计算机硬件是否支持64位操作系统。打开计算机的控制面板,点击“系统和安全”,然后点击“系统”。在“系统类型”一栏中,如果显示的是“32位操作系统”…

    other 2023年7月28日
    00
合作推广
合作推广
分享本页
返回顶部