算法设计 || 实验四 回溯算法-八皇后问题(纯手敲保姆级详细讲解+小白适用+头歌解析)

news2025/4/17 4:45:20

(一)八皇后问题描述

在一个8x8的棋盘上放置8个皇后,使得每个皇后都不会互相攻击,即任意两个皇后都不能在同一行、同一列或同一条对角线上。


(二)算法思路

由于八皇后问题的解法数量较多,本文将介绍其中一种解法——回溯法。

1.回溯法是一种通过遍历所有可能的解来寻找所有的解的算法。

如果一个候选解被发现不可能是一个正确的解,回溯算法会舍弃它,从而在候选解空间树中减少搜索的范围

PS:区别穷举法?

在于进行搜索范围的优化吖!及时止损~


2.使用一个一维数组来表示每个皇后的位置。

PS:为什么不用二维数组a[i][j]进行行和列的表示呢?

答:观察发现:每个皇后是不是分别占据了一层城堡,也就是从0一直到n-1行,每一行安排一个皇后的嘛,是不是了啦~

数组的下标代表皇后所在的行数,数组的值代表皇后所在的列数。


3.具体的解题思路如下:

从第一行开始放置皇后。

逐行放置皇后,直到最后一行。

在每一行中,逐个尝试放置皇后。

如果当前位置可以放置皇后,将皇后的位置记录在数组中,并进入下一行。

如果当前位置无法放置皇后,回溯到上一行,重新尝试放置皇后。

如果所有行都放置了皇后,输出解法。

PS:咦?问题又来了,这个皇后得把她们安排多少个超级大循环才可以给皇后一个家呢?

答:不知道要尝试多少次呀!那就直接while(1)呗!


(三)回溯算法整个代码的超级详细分析

以下是使用回溯法解决八皇后问题的C语言代码:

1.变量&函数:

变量名

变量类型

作用

queen

int[N]

用于记录每个皇后所在的列数

count

int

解法总数

函数名

参数

作用

check

int row

int col

判断当前位置是否可以放置皇后,如果可以则返回1,否则返回0。

backtrack

int row

回溯到上一行,并重新尝试放置皇后

main

返回int,调用backtrack函数求解八皇后问题,最终输出解法总数。

int queen[N] = {0}; // 用于记录每个皇后所在的列数

int count = 0; // 解法总数

int check(int row, int col) {}

void backtrack(int row) {}

int main() {}


2.皇后棋盘摆放0 or 1👉check

遍历一行中的每一个空,当前位置同一列或同一对角线上已经有皇后,返回0,否则返回1:

if (queen[i] == col ||

row - i == col - queen[i] ||

row - i == queen[i] - col) {

            return 0;

}

🐱‍🐉不同行:i表示行,queen[i]表示列,一行一个循环

🐱‍🐉同列:queen[i]==col

🐱‍🐉正对角线+反对角线:

  • 左下方:row-i==col-queen[i]

  • 右下方:row-i==queen[i]-col


3.回溯算法核心在此👉backtrack

输入参数:当前行数row当前正在尝试放置皇后的行数

PS:还是看不懂咋回溯嘛

从第1行开始,放置成功后再递归到下一行继续放置

如果在某一行中无法放置皇后,我们就需要回溯到上一行重新尝试其他位置。


🐱‍🐉当前行数等于N→找到了一种解法,解法总数count加1,直接返回,结束当前的递归。

PS:可不可以再详细一点

答:当我们成功地在第8行放置皇后后,说明我们已经找到了一种解法,此时我们可以将解法总数加1,并结束当前的递归,如下:

if (row == N) { // 找到了一个解法

        count++;

        return;

    }

🐱‍🐉当前行数不等于N→在当前行上尝试放置皇后。

  • for循环遍历当前行的每个位置

②每个位置(i,j)→调用函数check来判断是否可以放置皇后。

是:将该皇后的列数j记录在数组queen中的第row个位置上

③递归调用backtrack函数,尝试在下一行放置皇后。

在递归调用完成后,我们需要回溯到上一行,并将之前记录的皇后位置清空,以便重新尝试其他可能的解法。

   for (int i = 0; i < N; i++) { // 尝试在当前行的每个位置上放置皇后

        if (check(row, i)) {

            queen[row] = i;

            backtrack(row + 1);

            queen[row] = 0;

        }

    }

PS:更详细些

首先,使用for循环遍历当前行的每个位置,即从0到N-1,对于每个位置i,执行以下操作:

调用函数check(row, i)判断当前位置是否可以放置皇后。如果可以放置,就执行以下操作:

将当前皇后的列数i记录在数组queen中的第row个位置上,表示在当前行的第i列放置了皇后。

递归调用函数backtrack(row + 1),表示在下一行尝试放置皇后。

在递归完成后,需要回溯到上一行,并将之前记录的皇后位置清空,以便重新尝试其他可能的解法。具体来说,将queen[row]的值置为0,表示该行没有放置皇后。

当for循环执行完毕后,函数backtrack返回,结束当前的递归。

通过这段代码,我们可以在每个可行的位置上递归调用函数backtrack,不断地尝试放置皇后,直到找到所有的解法。在递归过程中,我们使用数组queen来记录每个皇后所在的列数,以便在回溯时清空之前记录的位置。函数check用于判断当前位置是否可以放置皇后,从而帮助我们进行决策。通过这些函数和代码的组合,我们可以有效地解决八皇后问题。

(四)C语言代码呈上 

第一种运行结果: 

#include <stdio.h>
#define N 8
int queen[N] = {0}; // 用于记录每个皇后所在的列数
int count = 0; // 解法总数
int check(int row, int col) {
    for (int i = 0; i < row; i++) {
        // 如果当前位置同一列或同一对角线上已经有皇后,返回 0
        if (queen[i] == col || row - i == col - queen[i] || row - i == queen[i] - col) {
            return 0;
        }
    }
    return 1;
}
void backtrack(int row) {
    if (row == N) { // 找到了一个解法
        count++;
        return;
    }
    for (int i = 0; i < N; i++) { // 尝试在当前行的每个位置上放置皇后
        if (check(row, i)) {
            queen[row] = i;
            backtrack(row + 1);
            queen[row] = 0;
        }
    }
}
int main() {
    backtrack(0); // 从第一行开始尝试放置皇后
    printf("%d", count);
    return 0;
}

第二种运行结果:

   

#include <stdio.h>
#define N 8
int queen[N] = {0}; // 用于记录每个皇后所在的列数
int check(int row, int col) {
    for (int i = 0; i < row; i++) {
        // 如果当前位置同一列或同一对角线上已经有皇后,返回 0
        if (queen[i] == col || row - i == col - queen[i] || row - i == queen[i] - col) {
            return 0;
        }
    }
    return 1;
}
void backtrack(int row) {
    if (row == N) { // 找到了一个解法
        for (int i = 0; i < N; i++) {
            printf("%d ", queen[i]);
        }
        printf("\n");
        return;
    }
    for (int i = 0; i < N; i++) { // 尝试在当前行的每个位置上放置皇后
        if (check(row, i)) {
            queen[row] = i;
            backtrack(row + 1);
            queen[row] = 0;
        }
    }
}
int main() {
    backtrack(0); // 从第一行开始尝试放置皇后
    return 0;
}

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

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

相关文章

mysql+Galera+haproxy高可用

文件下载地址环境准备 1.1准备三台服务器 服务器名称 Ip 描述 Node0 xxx.xxx.xxx.xxx Node1 xxx.xxx.xxx.xxx Node2 xxx.xxx.xxx.xxx 1.3 安装依赖包 sed -i s/SELINUXenforcing/SELINUXdisabled/g /etc/selinux/config setenforce 0 yum -y install lsof ne…

Axure教程—堆积面积图

本文将教大家如何用AXURE制作堆积面积图 一、效果介绍 如图&#xff1a; 预览地址&#xff1a;https://d4nsae.axshare.com 下载地址&#xff1a;https://download.csdn.net/download/weixin_43516258/87838160 二、功能介绍 简单填写中继器内容即可动态显示值 样式颜色等可…

热榜!阿里出品2023版Java架构师面试指南,涵盖Java所有核心技能

最近很多粉丝朋友私信我说&#xff1a;熬过了去年的寒冬却没熬过现在的内卷&#xff1b;打开Boss直拒一排已读不回&#xff0c;回的基本都是外包&#xff0c;薪资还给的不高&#xff0c;对技术水平要求也远超从前&#xff1b;感觉Java一个初中级岗位有上千人同时竞争&#xff0…

sqlmap的使用详细讲解

一、sqlmap介绍 简介&#xff1a;是一个自动化的sql注入工具&#xff0c;主要功能扫描、发现并利用给定的 url的sql注入漏洞&#xff0c;内置了很多插件 sqlmap支持的数据库&#xff1a; MySQL、oracle、sql-server、DB2.... 注意&#xff1a;sqlmap只用来检测和sq…

用户需求调研的6大注意事项

1、调研目标要清晰具体 调研目标需明确、清晰、具体&#xff0c;只有这样&#xff0c;才能确保在样本选择和问卷设置时&#xff0c;具有明确的目标性和针对性。 2、调研用户精细化梳理 由于用户间存在个体差异&#xff0c;如果只是随机选取部分用户作为调研样本的话&#xff0c…

Tcl-9. string 命令

字符串是 Tcl 中的基本数据类型&#xff0c;所以有大量的字符串操作命令。一个比较重要的问题就是 模式匹配&#xff0c;通过模式匹配将字符串与指定的模式&#xff08;格式&#xff09;相匹配来进行字符串的比较、搜索等 操作。下面string 命令提供了一些简单的模式匹配机制。…

MSP432学习笔记9:定时器A-----捕获

今日得以继续我的MSP432电赛速通之旅~~~ 目录 基础知识&#xff1a; 相关库函数&#xff1a; 一般配置步骤&#xff1a; 首先定义一个初始化函数&#xff1a; 1.复用引脚: 2.配置连续计数结构体: 3.初始化定时器连续计数: 4.配置捕获结构体: 5.初始化定时器为捕获: …

缺少vcruntime140.dll如何修复?电脑小白也能学会修复vcruntime140.dll教程

Vcruntime140.dll是一个用于微软的Visual C软件的动态链接库文件&#xff0c;DLL的全称是动态连接库(Dynamic Link Library)&#xff0c;它是许多不同软件中所共用的文件类型。这个文件被广泛用作其他软件的依赖库&#xff08;dependency&#xff09;。每当您尝试运行一个应用程…

大体量数据迁移成难题,亚马逊云科技如何让迁移能效两不误

逼真的人物设定&#xff0c;精美的主题布局&#xff0c;沉浸式的互动体验&#xff0c;交互式的多元场景……一系列虚拟与现实高度契合又相互映射的设定&#xff0c;成就了“元宇宙”游戏世界的无穷魅力。GVERSE开发的Blockman Go平台就是有着相当大体量的UGC&#xff08;用户生…

优秀的开源测试工具和框架推荐:精选十大神器!

目录 引言 Katalon Studio Selenium Appium JMeter SOAP UI Robot Framework Watir JUnit Robotium Citrus 结语 引言 你是一位测试从业者&#xff0c;时刻关注着最新的测试工具和框架。但在众多的选择面前&#xff0c;你是否感到困惑和无从下手&#xff1f; 别担…

Android音视频开发1:Android Studio安装

1.JDK安装&#xff0c;至少安装JAVA 1.7 对比项目 Android iOS 开发语言 Java Objective-c&#xff0c;Swift 系统开放性 Android源代码开放&#xff0c;开放性更好 封闭操作系统&#xff0c;开放性较差 系统安全性 源代码开放&#xff0c;安全性较差 封闭操作系统&…

电力电子课设|数控产生PWM波|使用51单片机输出占空比可调PWM波(按钮控制、数码管显示)速成教程

我们学校电气专业开始做电力电子的课设了&#xff0c;小组选了一项制作硬件电路的任务&#xff0c;里面有要求采用数控方式实现DC-DC电压变换的输出电压调节&#xff0c;数控在电路中的体现就是用单片机输出可调占空比的PWM作用于IRF520模块&#xff0c;实现电压的变化&#xf…

chatgpt赋能python:Python不等于0:为什么Python成为SEO的热门选择?

Python不等于0&#xff1a;为什么Python成为SEO的热门选择&#xff1f; 如果你正在寻找一门适合SEO的编程语言&#xff0c;Python可能就是你的不二选择。Python在SEO行业越来越流行&#xff0c;因为它具有许多与SEO相关的功能和特点。通过本文&#xff0c;我们将会介绍Python为…

Flutter调优--深入探究MediaQuery引起界面Rebuild的原因及解决办法 | 京东云技术团队

前言 我们可以通过MediaQuery.of(context)方法获取到一些设备和系统的相关信息&#xff0c;比如状态栏的高度、当前是否是黑暗模式等等&#xff0c;使用起来相当方便&#xff0c;但是也要注意可能引起的页面rebuild问题。本文会介绍一个典型的例子&#xff0c;并深入源码来探讨…

chatgpt赋能python:用Python下载MP3的方法

用Python下载MP3的方法 如果你想从互联网上下载MP3&#xff0c;那么你可以使用Python来实现这个任务。在本文中&#xff0c;我们将介绍如何用Python编写程序来下载MP3&#xff0c;同时还将分享一些有用的工具和资源。 Python中使用的库 要下载MP3&#xff0c;你需要使用Pyth…

接口测试简介以及接口测试用例设计思路

接口测试简介 1.什么是接口 接口就是内部模块对模块&#xff0c;外部系统对其他服务提供的一种可调用或者连接的能力的标准&#xff0c;就好比usb接口&#xff0c;他是系统向外接提供的一种用于物理数据传输的一个接口&#xff0c;当然仅仅是一个接口是不能进行传输的&#x…

如何快速入门高性能计算?五个实用学习建议分享

高性能计算 &#xff08;High-Performance Computing&#xff0c;HPC&#xff09;是指通过计算机技术实现高速运算&#xff0c;对大规模科学计算、数据分析、复杂制造等领域的研究与应用提供支撑。目前&#xff0c;HPC已经广泛应用于医学、天文、材料科学、地球科学、气象科学、…

【cmake 学习】cmake判断当前所处系统(CMAKE_SYSTEM_NAME)

目录 1、使用内置变量判断 2、使用变量 CMAKE_SYSTEM_NAME 判断 1、使用内置变量判断 cmake 内置了许多用于表示系统的变量&#xff0c;如 UNIX、WIN32、LINUX、IOS等。假设当前系统为Linux系统&#xff0c;那么 LINUX 变量的值为 1。 更多变量可以参考&#xff1a;cmake-v…

最近距离 | EXCEL中批量查找与原点最近距离的目标点

一 需求 企业送餐、物流、通勤、选址等经常会遇到这样的需求&#xff0c;仓储地是固定的&#xff0c;客户下单后由于客户的地址具有随机性&#xff0c;需按照地理位置分布结合仓储位置进行分析&#xff0c;按距离近及远合理分配仓储&#xff0c;以便节省配送成本。 本文就以这…

深度学习AI编译器-MLIR简介

1、什么是MLIR MLIR&#xff1a;Multi-Level Intermediate Representation 多级中间表达 LLVM下的子项目编译器基础框架统一IR格式&#xff0c;提高通用性和可复用性自带Tensor类型&#xff0c;目前主要用于深度学习领域 中间表达 IR&#xff08;Intermediate Representatio…