Java实现N皇后问题的双路径探索:递归回溯与迭代回溯算法详解

news2025/4/7 20:00:28

N皇后问题要求在N×N的棋盘上放置N个皇后,使得她们无法互相攻击。本文提供递归和循环迭代两种解法,并通过图示解释核心逻辑。


一、算法核心思想

使用回溯法逐行放置皇后,通过冲突检测保证每行、每列、对角线上只有一个皇后。发现无效路径时回退到上一状态。

冲突检测条件(关键):
  1. 同列冲突:col[i] == col[j]
  2. 对角线冲突:abs(col[i] - col[j]) == abs(i - j)

二、递归版本实现

  1. 流程图

  1. 时序图

  1. 代码解释

  1. 程序目的
    该代码用于解决N皇后问题,即在N×N棋盘上放置N个皇后,使其互不攻击(即任意两个皇后不在同一行、列或对角线上),返回所有可能的解。
  2. solveNQueens方法
    • 初始化结果列表result,用于存储所有解。
    • 调用backtrack方法启动递归回溯过程。
    • 参数n表示棋盘大小,cols数组记录每行皇后所在的列位置(索引为行,值为列)。
  3. backtrack递归核心
    • 终止条件:当row == n时,表示所有皇后已正确放置,将当前cols数组的拷贝加入结果(避免后续修改影响结果)。
    • 递归逻辑:遍历当前行的每一列col,若位置有效则放置皇后(cols[row] = col),并递归处理下一行(row + 1)。
  4. isValid冲突检查
    • 检查当前列col与之前所有行(0row-1)的皇后是否冲突:
      • 列冲突cols[i] == col,即同一列已有皇后。
      • 对角线冲突Math.abs(col - cols[i]) == row - i,即行差等于列差绝对值。
    • 若任一条件满足,返回false,否则位置有效。
  5. 主函数测试与输出
    • 测试n=4的皇后问题,调用solveNQueens获取所有解。
    • 使用Lambda表达式遍历打印每个解(如[1, 3, 0, 2]表示第0行皇后在1列,第1行在3列等)。
  6. 关键实现细节
    • 回溯剪枝:仅尝试有效位置,减少递归次数。
    • 结果存储:每次成功时创建新的ArrayList保存当前解,避免引用问题。
    • 递归层次:每层递归处理一行皇后,确保每行只有一个皇后。

示例输出:
对于n=4,输出两个解:[1, 3, 0, 2][2, 0, 3, 1],对应两种不同的棋盘布局方式。

  1. 代码实现
    1. 注意:下标从0开始
import java.util.ArrayList;
import java.util.List;

public class NQueensRecursive {
    public static List<List<Integer>> solveNQueens(int n) {
        List<List<Integer>> result = new ArrayList<>();
        backtrack(n, 0, new Integer[n], result);
        return result;
    }

    private static void backtrack(int n, int row, Integer[] cols, List<List<Integer>> result) {
        if (row == n) {
            result.add(new ArrayList<>(List.of(cols)));
            return;
        }
        for (int col = 0; col < n; col++) {
            if (isValid(cols, row, col)) {
                cols[row] = col;
                backtrack(n, row + 1, cols, result);
            }
        }
    }

    private static boolean isValid(Integer[] cols, int row, int col) {
        for (int i = 0; i < row; i++) {
            if (cols[i] == col || Math.abs(col - cols[i]) == row - i) {
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        List<List<Integer>> solutions = solveNQueens(4);
        solutions.forEach(System.out::println);
    }
}


三、循环迭代版本实现

  1. 时序图

  1. 流程说明
  1. 初始化阶段
    • 清空皇后位置数组
    • 从第一个皇后开始放置(j=1)
  2. 主循环逻辑
    • 每次循环尝试将当前皇后的位置右移一格
    • 通过check()验证当前位置是否:
      • 与已有皇后同列
      • 处于同一斜线
    • 合法时继续处理下一个皇后,非法时继续右移
    • 当完成最后一列放置时输出有效方案
  3. 回溯机制
    • 当某列所有位置尝试失败后
    • 重置当前列位置为0
    • 回溯到前一列继续尝试新位置
  4. 终止条件
    • 当回溯到j=0时说明所有可能性已穷尽
    • 程序正常结束

该实现通过非递归方式实现了经典的回溯算法,使用while循环和位置重置机制替代了递归调用栈,具有较好的空间效率。

  1. 代码实现
    1. 注意:下标从1开始
public class Test {
    // 定义4个皇后
    static final  Integer N = 4;
    // 存储皇后的列号
   static int[] q =  new int[N+1];
   // 方案数
   static int answer =0;

    public static void main(String[] args) {
        queen();

    }
    public static boolean check(int j){
        for(int i=1;i<j;i++){
            if(q[i]==q[j] || Math.abs(i-j)==Math.abs(q[i]-q[j])){ // 判断是否同列或同一斜线
            return false;
            }
        }
        return true;
    }
    public static void queen(){

       queenInit();
       int j = 1; // 表示正在摆放第j个皇后
        while(j>=1){

            q[j] ++;// 让第j个皇后的位置加1
            while(!check(j) && q[j]<=N){ // 不满足条件的话,就一直向后移动,为了防止越界,还需要判断q[j]的长度
                q[j]++;
            }
            // 判断
            if(q[j]<=N){// 表示第j个位置,合法

                if(j==N){// 最后一个皇后已经摆放完毕了
                    answer++;
                    System.out.print("方案"+answer);
                    System.out.print("结果为:");
                    for (int i = 1; i <=N ; i++) {
                        System.out.print(q[i]+",");
                    }
                    System.out.println();
                }else{// 继续找下一个皇后的摆放位置
                    j++;
                }
            }else{
                // 没有位置摆放了,需要回溯到上一次。
                q[j]=0; // 重置位置
                j--;
            }
        }
    }

    // 皇后初始化
    public static void queenInit(){
        for(int i=1;i<=N;i++){
            q[i]=0;
        }
    }
}



四、算法流程图示(以4皇后为例)

步骤分解:
1. 放置行0的皇后在列0
   Q . . .
   . . . .
   . . . .
   . . . .

2. 行1尝试列0(冲突)→ 尝试列1(冲突)→ 列2有效
   Q . . .
   . . Q .
   . . . .
   . . . .

3. 行2尝试所有列均冲突,回溯到行1
   Q . . .
   . . . . ← 行1无法继续
   . . . .
   . . . .

4. 行1移动到列3
   Q . . .
   . . . Q
   . . . .
   . . . .

5. 行2尝试列1有效
   Q . . .
   . . . Q
   . Q . .
   . . . .

6. 行3无有效列,回溯→最终找到解:
   [1, 3, 0, 2] 对应棋盘:
   . Q . .
   . . . Q
   Q . . .
   . . Q .

五、算法对比

特性递归版本循环迭代版本
代码复杂度简洁,易理解需手动管理状态栈
内存消耗有栈深度限制显式栈结构,可控性强
适用场景小规模数据,代码可读性优先避免栈溢出,大数据量更稳定

两种方法时间复杂度均为O(N!),实际效率相近,选择依据具体场景需求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2329415.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

谷歌开源单个 GPU 可运行的Gemma 3 模型,27B 超越 671B 参数的 DeepSeek

自从 DeepSeek 把训练成本打下来之后&#xff0c;各个模型厂家现在不再堆参数进行模型的能力对比。而是转向了训练成本优化方面&#xff0c;且还要保证模型能力不减反增的效果。包括使用较少的模型参数&#xff0c;降低 GPU 使用数量&#xff0c;降低模型内存占用等等技术手段。…

C++_类和对象(下)

【本节目标】 再谈构造函数Static成员友元内部类匿名对象拷贝对象时的一些编译器优化再次理解封装 1. 再谈构造函数 1.1 构造函数体赋值 在创建对象时&#xff0c;编译器通过调用构造函数&#xff0c;给对象中各个成员变量一个合适的初始值。 class Date { public:Date(in…

Docker设置代理

目录 前言创建代理文件重载守护进程并重启Docker检查代理验证 前言 拉取flowable/flowable-ui失败&#xff0c;用DaoCloud源也没拉下来&#xff0c;不知道是不是没同步。索性想用代理拉镜像。在此记录一下。 创建代理文件 创建docker代理配置 sudo mkdir -p /etc/systemd/s…

一键自动备份:数据安全的双重保障

随着数字化时代的到来&#xff0c;数据已成为企业和个人不可或缺的核心资产。在享受数据带来的便捷与高效的同时&#xff0c;数据丢失的风险也随之增加。因此&#xff0c;备份文件的重要性不言而喻。本文将深入探讨备份文件的重要性&#xff0c;并介绍两种实用的自动备份方法&a…

HeidiSQL:多数据库管理工具

HeidiSQL 是一款广受欢迎的免费开源数据库管理工具&#xff0c;专为数据库管理员及开发者设计。无论您是刚接触数据库领域的新手&#xff0c;还是需要同时处理多种数据库系统的专业开发者&#xff0c;该工具都能凭借其直观的界面和强大的功能&#xff0c;助您轻松完成数据管理任…

医药档案区块链系统

1. 医生用户模块​​ ​​目标用户​​&#xff1a;医护人员 ​​核心功能​​&#xff1a; ​​检索档案​​&#xff1a;通过关键词或筛选条件快速定位患者健康档案。​​请求授权​​&#xff1a;向个人用户发起档案访问权限申请&#xff0c;需经对方确认。​​查看档案​…

蓝桥云客--浓缩咖啡液

4.浓缩咖啡液【算法赛】 - 蓝桥云课 问题描述 蓝桥杯备赛选手小蓝最近刷题刷到犯困&#xff0c;决定靠咖啡续命。他手上有 N 种浓缩咖啡液&#xff0c;浓度分别是 A1​%, A2​%, …, AN​%&#xff0c;每种存货都是无限的。为了提神又不炸脑&#xff0c;小蓝需要按比例混合这…

SQLark(百灵连接):一款面向信创应用开发者的数据库开发和管理工具

SQLark&#xff08;百灵连接&#xff09;是一款面向信创应用开发者的数据库开发和管理工具&#xff0c;用于快速查询、创建和管理不同类型的数据库系统。 目前可以支持达梦数据库、Oracle 以及 MySQL。 SQL 智能编辑器 基于语法语义解析实现代码补全能力&#xff0c;为你提供…

计算机视觉——为什么 mAP 是目标检测的黄金标准

概述 在目标检测领域&#xff0c;有一个指标被广泛认为是衡量模型性能的“黄金标准”&#xff0c;它就是 mAP&#xff08;Mean Average Precision&#xff0c;平均精确率均值&#xff09;。如果你曾经接触过目标检测模型&#xff08;如 YOLO、Faster R-CNN 或 SSD&#xff09;…

Frame Of Reference压缩算法

文章目录 1_概述2_算法基本步骤3_过程优化4_优势以及局限5_模拟实现6_总结 1_概述 Frame of Reference&#xff08;FoR&#xff09;压缩算法 是一种用于压缩数值数据的算法&#xff0c;特别是在处理大规模数据集时&#xff0c;利用数据的局部性和重复性来减少存储和传输的开销…

esp32cam 开发板搭载ov3660摄像头在arduino中调用kimi进行图像识别

首先呢,最近搞一个项目,需要一个摄像头拍摄图片 就买了个ov3660开发板,用的esp32S芯片 淘宝商家给的教程是arduino的,所以先用arduino跑起来 arduino配置esp32-cam开发环境 - 简书1、安装arduino https://www.arduino.cc/en/Main/Software?setlang=cn 2、配置esp32 打开…

二十种中药果实识别分类系统,Python/resnet18/pytorch

二十种中药果实识别分类系统,Python/resnet18/pytorch 基于pytorch训练, resnet18网络&#xff0c;可用于训练其他分类问题&#xff0c;也可自己重新训练 20类中药材具体包括&#xff1a;(1) 补骨脂&#xff0c;(2) 草豆蔻&#xff0c;(3) 川楝子&#xff0c;(4) 地肤子&…

如何实现两个视频融合EasyCVR平台的数据同步?详细步骤指南

有用户咨询&#xff0c;现场需要数据库同步&#xff0c;如何将两个EasyCVR平台的数据进行同步呢&#xff1f; 这篇文章我们将详细介绍如何通过简单的接口调用&#xff0c;高效完成两个平台的数据同步操作。 1&#xff09;获取token 使用Postman调用登录接口&#xff0c;获取…

WindowsPE文件格式入门05.PE加载器LoadPE

https://bpsend.net/thread-316-1-1.html LoadPE - pe 加载器 壳的前身 如果想访问一个程序运行起来的内存,一种方法就是跨进程读写内存,但是跨进程读写内存需要来回调用api,不如直接访问地址来得方便,那么如果我们需要直接访问地址,该怎么做呢?.需要把dll注进程,注进去的代码…

使用Cusor 生成 Figma UI 设计稿

一、开发环境 系统&#xff1a;MacOS 软件版本&#xff1a; Figma&#xff08;网页或APP版&#xff09; 注&#xff1a;最好是app版&#xff0c;网页版figma 没有选项 import from manifest app下载地址&#xff1a;Figma Downloads | Web Design App for Desktops & …

Golang的文件同步与备份

Golang的文件同步与备份 一、Golang介绍 也称为Go语言&#xff0c;是谷歌开发的一种编程语言&#xff0c;具有高效的并发编程能力和出色的内存管理。由于其快速的编译速度和强大的标准库&#xff0c;Golang在网络应用、云平台和大数据等领域得到了广泛应用。 二、文件同步与备份…

如何用人工智能大模型,进行作业批改?

今天我们学习人工智能大模型如何进行作业批改。手把手学习视频请访问https://edu.csdn.net/learn/40402/666452 第一步&#xff0c;进入讯飞星火。打开google浏览器&#xff0c;输入百度地址后&#xff0c;搜索”讯飞星火”&#xff0c;在搜索的结果中&#xff0c;点第一个讯飞…

MATLAB之数据分析图系列 三

三维堆叠柱状图 Bar3StackPlot.m文件 clc; clear; close all; %三维堆叠柱状图 %% 数据准备 % 读取数据 load data.mat % 初始化 dataset X; s 0.4; % 柱子宽度 n size(dataset,3); % 堆叠组数%% 图片尺寸设置&#xff08;单位&#xff1a;厘米&#xff09; figureUnits c…

python爬虫:DrissionPage实战教程

如果本文章看不懂可以看看上一篇文章&#xff0c;加强自己的基础&#xff1a;爬虫自动化工具&#xff1a;DrissionPage-CSDN博客 案例解析&#xff1a; 前提&#xff1a;我们以ChromiumPage为主&#xff0c;写代码工具使用Pycharm&#xff08;python环境3.9-3.10&#xff09; …

一、STM32简介

一、实验器材介绍 二、STM32简介 1.STM32 名词解释 STM32是ST公司基于ARM Cortex-M内核开发的32位微控制器。 ST&#xff0c;指ST公司&#xff08;意法半导体&#xff09;;M&#xff0c;MicroController 微控制器&#xff08;MCU,MicroController Unit 微控制器单元/单片机&…