[递归回溯] 八皇后问题

例题(15.4) 八皇后 (1060)

题目描述

会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题。
对于某个满足要求的8皇后的摆放方法,定义一个皇后串a与之对应,即a=b1b2...b8,其中bi为相应摆法中第i行皇后所处的列数。已经知道8皇后问题一共有92组解(即92个不同的皇后串)。
给出一个数b,要求输出第b个串。串的比较是这样的:皇后串x置于皇后串y之前,当且仅当将x视为整数时比y小

关于输入

第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数b(1 <= b <= 92)

关于输出

n行,每行输出对应一个输入。输出应是一个正整数,是对应于b的皇后串

例子输入
2
1
92
例子输出
15863724
84136275
解题分析

我们可以使用深度优先搜索(DFS)和回溯的方法来解决八皇后问题。以下是算法的详细步骤:

1. 初始化棋盘:首先,我们创建一个一维数组`board`来代表棋盘,数组的索引代表棋盘的行,索引对应的值代表在该行的皇后所在的列。例如,`board[0] = 3`表示第一行的皇后在第四列。

2. 搜索所有可能的解:我们使用递归函数`solve`来进行深度优先搜索。在这个函数中,我们从第一行开始,尝试在每一列放置皇后。对于每一列,我们使用`is_valid`函数来检查在这个位置放置皇后是否有效。如果有效,我们就在这个位置放置皇后,然后递归地在下一行做同样的事情。如果我们已经在所有的行上放置了皇后,那么我们就找到了一个解,将其添加到`solutions`数组中。

3. 检查有效性:在`is_valid`函数中,我们检查新的皇后是否和已经放置的皇后在同一列或同一对角线上。我们通过比较新的皇后的位置和已经放置的皇后的位置来实现这一点。如果新的皇后和任何一个已经放置的皇后在同一列或同一对角线上,那么这个位置就是无效的,我们需要在其他列上尝试放置皇后。

4. 处理输入和输出:在`main`函数中,我们首先调用`solve`函数来找到所有的解,然后处理输入数据。对于每个输入的索引,我们从`solutions`数组中找到相应的解,然后打印出来。

这个算法的时间复杂度是O(N!),其中N是棋盘的大小(在这个问题中,N=8)。这是因为在最坏的情况下,我们需要尝试所有可能的皇后放置方式。然而,由于我们使用了回溯的方法,当我们发现某个皇后的位置无效时,我们会立即停止在这个路径上的搜索,这大大减少了搜索空间,提高了效率。

并且注意到:

在国际象棋中,两个棋子处在同一对角线上,当且仅当它们的行索引之差等于列索引之差,或者行索引之差等于列索引之差的负数。这是因为在对角线上的每个方格,其行和列的增减速度是相同的。

在我们的代码中,我们使用了以下的代码来检查新的皇后是否和已经放置的皇后在同一对角线上:

```c
abs(board[i] - col) == abs(i - row)
```

这里,`board[i]`和`i`分别是已经放置的皇后的列和行,`col`和`row`是新的皇后的列和行。如果新的皇后和已经放置的皇后在同一对角线上,那么他们的行索引之差`abs(i - row)`应该等于列索引之差`abs(board[i] - col)`。

这样,我们就可以很容易地检查新的皇后是否和已经放置的皇后在同一对角线上。

代码实现
#include <stdio.h>
#include <stdlib.h>

#define N 8
#define TOTAL_SOLUTIONS 92

int solutions[TOTAL_SOLUTIONS][N] = {0};
int count = 0;

int is_valid(int board[N], int row, int col) {
    for (int i = 0; i < row; i++) {
        if (board[i] == col || abs(board[i] - col) == abs(i - row)) {
            return 0;
        }
    }
    return 1;
}

void solve(int board[N], int row) {
    if (row == N) {
        for (int i = 0; i < N; i++) {
            solutions[count][i] = board[i] + 1;
        }
        count++;
    } else {
        for (int col = 0; col < N; col++) {
            if (is_valid(board, row, col)) {
                board[row] = col;
                solve(board, row + 1);
            }
        }
    }
}

int main() {
    int board[N] = {0};
    solve(board, 0);

    int t;
    scanf("%d", &t);
    while (t--) {
        int b;
        scanf("%d", &b);
        for (int i = 0; i < N; i++) {
            printf("%d", solutions[b-1][i]);
        }
        printf("\n");
    }
    return 0;
}

当然,我们还可以选择另外一种办法:

这个程序的目标和之前的程序一样,都是要解决八皇后问题。它使用了一种稍微不同的方法来实现深度优先搜索和回溯。

以下是这个程序的主要步骤:

1. 初始化棋盘和其他相关数组:`board`数组用来存储每个皇后的位置,`left1`和`right1`数组用来存储左对角线和右对角线上已经放置了皇后的位置,`col`数组用来存储已经放置了皇后的列。`solution`数组用来存储所有的解,`count`变量用来记录已经找到的解的数量。

2. 搜索所有可能的解:`dfs`函数是一个递归函数,用于通过深度优先搜索来找到所有可能的解。在这个函数中,我们从第一行开始,尝试在每一列放置皇后。对于每一列,我们检查在这个位置放置皇后是否有效,即这个位置的列、左对角线和右对角线上是否已经放置了皇后。如果有效,我们就在这个位置放置皇后,并标记这个位置的列、左对角线和右对角线已经被占用,然后递归地在下一行做同样的事情。如果我们已经在所有的行上放置了皇后,那么我们就找到了一个解,将其添加到`solution`数组中。

3. 处理输入和输出:在`main`函数中,我们首先调用`dfs`函数来找到所有的解,然后处理输入数据。对于每个输入的索引,我们从`solution`数组中找到相应的解,然后打印出来。

这个程序的关键在于它如何使用`col`、`left1`和`right1`数组来快速检查在特定位置放置皇后是否有效。这是一种常见的方法,用于优化八皇后问题的解决方案。通过这种方法,我们可以在常数时间内检查在特定位置放置皇后是否有效,这大大提高了算法的效率。

在这个程序中,`left1`和`right1`数组被用来检查在特定位置放置皇后是否会与已经放置的皇后在同一对角线上。这是通过计算行和列的索引之和或之差来实现的。

首先,我们需要理解在一个二维的棋盘上,对于任何一个在对角线上的格子,它们的行索引和列索引之和(对于右对角线)或之差(对于左对角线)都是常数。

例如,对于右对角线,如果我们从左上角开始,向右下角移动,那么每个格子的行索引和列索引之和都是相同的。同样,对于左对角线,如果我们从左下角开始,向右上角移动,那么每个格子的行索引和列索引之差都是相同的。

在这个程序中,`right1[row+j]`被用来表示右对角线,`row+j`的值对于同一对角线上的所有格子都是相同的。`left1[row-j+9]`被用来表示左对角线,`row-j+9`的值对于同一对角线上的所有格子都是相同的。这里加9是为了避免数组索引为负数。

如果在某个位置放置了皇后,那么我们就将相应的`left1`和`right1`数组的值设为1,表示这个对角线上已经放置了皇后。在尝试在其他位置放置皇后时,我们就可以通过检查`left1`和`right1`数组来快速确定这个位置的对角线上是否已经放置了皇后。

因此,`left1`和`right1`数组是一种有效的方法,可以在常数时间内检查在特定位置放置皇后是否会与已经放置的皇后在同一对角线上。

#include <iostream>
using namespace std;

int board[9]={0},left1[20]={0},right1[20]={0},col[9]={0};
int solution[93][9];
int count=1;

void dfs(int row,int step){
    if(step>8){
        for(int i=1;i<=8;i++){
            solution[count][i]=board[i];
        }
        count++;
        return;
    }
    for(int j=1;j<=8;j++){
        if(col[j]==0 && left1[row-j+9]==0 && right1[row+j]==0){
            board[row]=j;
            col[j]=1; left1[row-j+9]=1; right1[row+j]=1;
            dfs(row+1,step+1);
            col[j]=0; left1[row-j+9]=0; right1[row+j]=0;
        }
    }
}

int main() {
    int n; cin>>n;
    dfs(1,1);
    while(n--){
        int b; cin>>b;
        for(int i=1;i<=8;i++){
            cout<<solution[b][i];
        }
        cout<<endl;
    }
	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring的依赖注入,依赖注入的基本原则,依赖注入的优势

文章目录 Spring的依赖注入依赖注入的基本原则依赖注入有什么优势查找定位操作与应用代码完全无关。有哪些不同类型的依赖注入实现方式&#xff1f;构造器依赖注入和 Setter方法注入的区别 Spring的依赖注入 控制反转IoC是一个很大的概念&#xff0c;可以用不同的方式来实现。…

Vue打包错误UnhandledPromiseRejectionWarning: CssSyntaxError

错误详情如下&#xff1a; building for production...Error processing file: static/css/app.3d5caae7aaba719754d7d5c30b864551.css (node:33011) UnhandledPromiseRejectionWarning: CssSyntaxError: /Users/yt/Documents/BM/sims-plus/sims-website/static/css/app.3d5caa…

USB简介系列-02

系列文章目录 USB简介之二 文章目录 系列文章目录USB数据流一、USB总线二、USB收发器三、USB速率识别三、USB总线状态总结USB数据流 本部分讨论USB低速和全速模式下的数据流。 一、USB总线 想象一下USB主机根集器下级联了集线器和设备的设置,如下图示。我们需要记住的是,在…

Redis核心数据结构

目录 五种基础数据结构 string hash list set zset 用zset实现微博热搜 scan遍历 高频问题 五种基础数据结构 string 单个赋值set 批量赋值/取值 msetmget 设置不存在字符串setnx, 如果不存在, 则设置成功返回1, 如果存在返回0, 可以当做分布式锁 删除值 设置过期时…

Redis-缓存设计

缓存穿透 缓存穿透是指查询一个根本不存在的数据&#xff0c; 缓存层和存储层都不会命中&#xff0c; 通常出于容错的考虑&#xff0c; 如果从存储层查不到数据则不写入缓存层。 缓存穿透将导致不存在的数据每次请求都要到存储层去查询&#xff0c; 失去了缓存保护后端存储的…

使用360浏览器插件刷新网页

使用360浏览器插件刷新网页 1.打开360浏览器->扩展程序->更多扩展。 2.扩展中心->搜索”网页自动刷新”&#xff0c;然后安装。 3.在要学习的网页上&#xff0c;扩展程序中使用页面自动刷新插件。 4.如果页面打开慢就把10改大&#xff0c;比如改成15&#xff0…

指定训练使用的GPU个数,没有指定定gpu id,训练在其中两个gpu上执行,但是线程id分布在所有4个gpu上,为什么?如何解决?

目录 问题背景 1 线程id分布在所有gpu&#xff08;包括未启用的gpu&#xff09;上原因&#xff1a; 2 在解决这个问题时&#xff0c;可以采取以下步骤&#xff1a; 3 修正深度学习框架默认使用所有可见 GPU 的问题 1 TensorFlow&#xff1a; 2 PyTorch&#xff1a; 3 K…

FreeRTOS深入教程(中断管理)

文章目录 前言一、为什么要为中断设计一套API二、两套函数区别对比三、两类中断四、FreeRTOS中SYSTICK和PendSV中断的作用总结 前言 本篇文章来分析FreeRTOS中的中断&#xff0c;中断在FreeRTOS中也是非常重要的&#xff0c;那么这篇文章将带大家来学习一下FreeRTOS中的中断处…

go对rabbitmq基本操作

一、安装rabbitmq 1、直接使用docker拉取镜像 docker pull rabbitmq:3.82、启动容器 docker run \-e RABBITMQ_DEFAULT_USERadmin \-e RABBITMQ_DEFAULT_PASS123456 \-v mq-plugins:/plugins \--name rabbit01 \--hostname rabbit01 --restartalways \-p 15672:15672 \-p 5672:…

数据结构 / 计算机内存分配

1. Linux 32位系统内存分配 栈(stack): 先进后出, 栈区变量先定义的后分配内存, 栈区地址从高到低分配堆(heap): 先进先出, 栈区变量先定义的先分配内存, 堆区地址从低到高分配堆栈溢出: 表示的是栈区内存耗尽, 称为溢出. 例如: 每次调用递归都需要在栈区申请内存, 如果递归太深…

【LLM_04】自然语言处理基础_2

一、神经网络1、循环神经网络&#xff08;RNN&#xff09;2、门控循环单元&#xff08;GRU&#xff09;3、长短期记忆网络&#xff08;LSTM&#xff09;4、双向RNN5、卷积神经网络&#xff08;CNN&#xff09; 二、注意力机制1、注意力机制原理介绍2、注意力机制的各种变式3、注…

车载通信架构 —— 传统车内通信网络FlexRay(较高速度高容错、较灵活拓扑结构)

车载通信架构 —— 传统车内通信网络FlexRay(较高速度高容错、较灵活拓扑结构) 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,…

leetCode 1080.根到叶路径上的不足节点 + 递归 + 图解

给你二叉树的根节点 root 和一个整数 limit &#xff0c;请你同时删除树中所有 不足节点 &#xff0c;并返回最终二叉树的根节点。假如通过节点 node 的每种可能的 “根-叶” 路径上值的总和全都小于给定的 limit&#xff0c;则该节点被称之为 不足节点 &#xff0c;需要被删除…

目录树自动生成器 golang+fyne

go tree 代码实现请看 gitee 仓库链接 有很多生成目录树的工具&#xff0c;比如windows自带的tree命令&#xff0c;nodejs的treer&#xff0c;tree-cli等等。这些工具都很成熟、很好用&#xff0c;有较完善的功能。 但是&#xff0c;这些工具全部是命令式的&#xff0c;如果…

vs2019中出现Debug Error的原因

一般出现这种错误表示你的某个变量没有正确赋值&#xff0c;或者说本身在你的C程序中加了assert断言&#xff0c;assert的作用是先计算表达式expression,如果其值为假&#xff0c;那么它会打印一条错误信息 #include<assert.h> void assert(int expression); 例子&…

01、copilot+pycharm

之——free for student 目录 之——free for student 杂谈 正文 1.for student 2.pycharm 3.使用 杂谈 copilot是github推出的AI程序员&#xff0c;将chatgpt搬到了私人终端且无token限制&#xff0c;下面是使用方法。 GitHub Copilot 是由 GitHub 与 OpenAI 合作开发的…

网络篇---第一篇

系列文章目录 文章目录 系列文章目录前言一、HTTP 响应码有哪些?分别代表什么含义?二、Forward 和 Redirect 的区别?三、Get 和 Post 请求有哪些区别?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男…

【ArcGIS Pro微课1000例】0037:ArcGIS Pro中模型构建器的使用---以shp批量转kml/kmz为例

文章目录 一、ArcGIS Pro模型构建器介绍二、shp批量转kml/kmz1. 打开模型构建器2. 添加工作空间4. 添加【创建要素图层】工具5. 添加【图层转kml】工具6. 输出文件命名7. 运行模型三、模型另存为1.py文件2. 保存为工具一、ArcGIS Pro模型构建器介绍 模型构建器是一种可视化编程…

项目去除git版本控制

我 | 在这里 &#x1f575;️ 读书 | 长沙 ⭐软件工程 ⭐ 本科 &#x1f3e0; 工作 | 广州 ⭐ Java 全栈开发&#xff08;软件工程师&#xff09; &#x1f383; 爱好 | 研究技术、旅游、阅读、运动、喜欢流行歌曲 ✈️已经旅游的地点 | 新疆-乌鲁木齐、新疆-吐鲁番、广东-广州…

C++连接MySQL失败解决

通过localhost连接&#xff0c;错误 遂改用127.0.0.1&#xff0c;协议不匹配&#xff0c;错误 在my.conf添加skip–sslon&#xff0c;重启mysql&#xff0c;连接成功 ref: https://www.cnblogs.com/walkersss/p/17037086.html
最新文章