算法总结——八皇后问题(三种解法)

2023-05-16

问题描述

会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如何将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


解题思路一

因为要求出92种不同摆放方法中的任意一种,所以我们不妨把92种不同的摆放方法一次性求出来,存放在一个数组里。为求解这道题我们需要有一个矩阵仿真棋盘,每次试放一个棋子时只能放在尚未被控制的格子上,一旦放置了一个新棋子,就在它所能控制的所有位置上设置标记,如此下去把八个棋子放好。当完成一种摆放时,就要尝试下一种。若要按照字典序将可行的摆放方法记录下来,就要按照一定的顺序进行尝试。也就是将第一个棋子按照从小到大的顺序尝试;对于第一个棋子的每一个位置,将第二个棋子从可行的位置从小到大的顺序尝试;在第一第二个棋子固定的情况下,将第三个棋子从可行的位置从小到大的顺序尝试;依次类推。
首先,我们有一个8*8的矩阵仿真棋盘标识当前已经摆放好的棋子所控制的区域。用一个有92行每行8个元素的二维数组记录可行的摆放方法。用一个递归程序来实现尝试摆放的过程。基本思想是假设我们将第一个棋子摆好,并设置了它所控制的区域,则这个问题变成了一个7皇后问题,用与8皇后同样的方法可以获得问题的解。那我们就把重心放在如何摆放一个皇后棋子上,摆放的基本步骤是:从第1到第8个位置,顺序地尝试将棋子放置在每一个未被控制的位置上,设置该棋子所控制的格子,将问题变为更小规模的问题向下递归,需要注意的是每次尝试一个新的未被控制的位置前,要将上一次尝试的位置所控制的格子复原。


参考程序一

#include <stdio.h>
#include <math.h>
int queenPlaces[92][8]; //存放92种皇后棋子的摆放方法
int count = 0;
int board[8][8]; //仿真棋盘
void putQueen(int ithQueen); //递归函数,每次摆好一个棋子

void main()
{
   int n, i, j;  
    for(i = 0; i < 8; i++){  // 初始化
	    for(j = 0; j < 8; j++)
	        board[i][j] = -1;
	    for(j = 0; j < 92; j++)
	        queenPlaces[j][i] = 0;
    }
    putQueen(0); //从第0个棋子开始摆放,运行的结果是将queenPlaces生成好
   scanf("%d", &n);
   for(i = 0; i < n; i++){
        int ith;
        scanf("%d", &ith);
        for(j = 0; j < 8; j++)
           printf("%d", queenPlaces[ith - 1][j]);
        printf("\n");
    }
}
void putQueen(int ithQueen){
     int i, k, r;
     if(ithQueen == 8){
	     count ++;
	     return;
     }
     for(i = 0; i < 8; i++){
         if(board[i][ithQueen] == -1){
			 //摆放皇后
             board[i][ithQueen] = ithQueen;
			 //将其后所有的摆放方法的第ith个皇后都放在i+1的位置上
			 //在i增加以后,后面的第ith个皇后摆放方法后覆盖此时的设置
		     for(k = count; k < 92; k++)
		         queenPlaces[k][ithQueen] = i + 1;
			 //设置控制范围
	         for(k = 0; k < 8; k++)
			 for(r = 0; r < 8; r++)
				 if(board[k][r] == -1 && 
					 (k == i || r == ithQueen || abs(k - i) == abs(r - ithQueen))) 
		             board[k][r] = ithQueen;
			 //向下级递归
             putQueen(ithQueen + 1);
             //回溯,撤销控制范围
             for(k = 0; k < 8; k++)
			 for(r = 0; r < 8; r++)
					 if(board[k][r] == ithQueen) board[k][r] = -1;
		 }
	 }
}


解题思路二

上面的方法用一个二维数组来记录棋盘被已经放置的棋子的控制情况,每次有新的棋子放置时用了枚举法来判断它控制的范围。还可以用三个一维数组来分别记录每一列,每个45度的斜线和每个135度的斜线上是否已经被已放置的棋子控制,这样每次有新的棋子放置时,不必再搜索它的控制范围,可以直接通过三个一维数组判断它是否与已经放置的棋子冲突,在不冲突的情况下,也可以通过分别设置三个一维数组的相应的值,来记录新棋子的控制范围。

参考程序二

#include <stdio.h>
int  record[92][9], mark[9], count = 0; //record记录全部解,mark记录当前解;
bool range[9], line1[17], line2[17]; //分别记录列方向,45度,135度方向上被控制的情况
void tryToPut(int ); //求全部解的过程
void main()
{
	int i, testtimes, num;
	scanf("%d", &testtimes);
	
	for(i = 0; i <=8; i++)
		range[i] = true;
	for(i = 0; i < 17; i ++)
		line1[i] = line2[i] = true;

	tryToPut(1);

	while(testtimes --){
		scanf("%d", &num);
		for(i = 1; i <=8; i++)
			printf("%d", record[num - 1][i]);
		printf("\n");
	}
}

void tryToPut(int i){
    if(i > 8){ //如果最后一个皇后被放置完毕,将当前解复制到全部解中
	    for(int k = 1; k < 9; k ++) 
		    record[count][k] = mark[k];
	    count ++;
     }					
     for(int j=1; j<=8; j++){ 逐一尝试将当前皇后放置在不同列上
	     if(range[j] && line1 [i + j] && line2[i - j + 9]){ //如果与前面的不冲突,
                                               //则把当前皇后放置在当前位置
		    mark[i] = j;
		    range[j] = line1[i + j] = line2[i - j + 9] = false;
            tryToPut(i + 1);
		    range[j] = line1[i + j] = line2[i - j + 9] = true;
	    }
    }
}


解题思路三

这个题目也可以不用仿真棋盘来模拟已放置棋子的控制区域,而只用一个有8个元素的数组记录已经摆放的棋子摆在什么位置,当要放置一个新的棋子时,只需要判断它与已经放置的棋子之间是否冲突就行了。

参考程序三

#include <stdio.h>
int ans[92][8], n, b, i, j, num, hang[8];
void queen(int i){
	int j, k;
	if(i == 8){ //一组新的解产生了
		for(j = 0; j < 8; j++)  ans[num][j] = hang[j] + 1;
		num++;
		return;
	}
	for (j=0; j<8; j++){ //将当前皇后i逐一尝试放置在不同的列
        for(k=0; k<i; k++) //逐一判定i与前面的皇后是否冲突
            if( hang[k] == j || (k - i) == (hang[k] - j) || (i - k) == (hang[k] - j )) break;
		if (k == i) {  //放置i,尝试第i+1个皇后
			hang[i] = j;
			queen(i + 1);
		}
	}
}
void main( ){
	num=0;
	queen(0);
	scanf(“%d”, &n);
	for(i = 0; i < n; i++){
		scanf(“%d”, &b);
		for(j = 0; j < 8; j++)  printf(“%d”, ans[b - 1][j]);
		printf(“\n”);
	}
}


实现中常见的问题

问题一: 使用枚举法,穷举8个皇后的所有可能位置组合,逐一判断是否可以互相被吃掉,得到超时错误;
问题二:对于多组输入,有多组输出,没有在每组输出后加换行符,得到格式错;
问题三:对输入输出的函数不熟悉,试图将数字转换成字符或者将8个整数转换成8位的十进制整数来完成输出,形成不必要的冗余代码。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

算法总结——八皇后问题(三种解法) 的相关文章

  • 嵌入式实时操作系统3——任务切换

    任务切换原理 假设有一程序 xff0c 程序内有一个无限循环 xff0c 在循环内部有5个表达式 xff0c 代码如下 xff1a 程序在循环中 xff0c 会依次执行表达式1 表达式2 表达式3 表达式4 表达式5 表达式1无限循环 假设
  • 嵌入式软件设计必看书籍

    提高C语言编程能力 以上4本书籍可以提高C语言编程能力 xff0c 深入理解C语言指针用法 xff0c 深入理解C语言标准 提高软件架构设计能力 以上2本书籍掌握以下知识 xff1a 1 软件设计原则 2 软件设计模式 3 软件设计构架 4
  • 如何使用 Docker 进行编译和开发

    简介 xff1a 本文主要为大家讲解不同环境下如何使用docker进行日常开发和编译 镜像下载 域名解析 时间同步请点击 阿里巴巴开源镜像站 一 Linux环境开发 适用于Linux环境开发者 xff0c 有专门代码服务器或虚拟机 1 安装
  • 嵌入式实时操作系统9——中断系统

    1 中断是什么 中断是计算机中一个非常重要的概念 xff0c 现代计算机中毫无例外地都要采用中断技术 早期的计算机没有中断系统 xff0c 人们往往需要等上一个任务运行结束才能运行下一个任务 xff0c 这极大的限制了计算机的执行效率 早期
  • 从零开始构建嵌入式实时操作系统1——任务切换

    1 前言 随着计算机技术和微电子技术的迅速发展 xff0c 嵌入式系统应用领域越来越广泛 xff0c 尤其是其具备低功耗技术的特点得到人们的重视 随着工信部提出NB IoT基站建设具体目标 三大运营商加速建设 xff0c 即将迎来万物互联的
  • 从零开始构建嵌入式实时操作系统2——重构

    1 前言 本人是一个普通的中年程序员 xff0c 并不是圈内的大牛 xff0c 写嵌入式操作系统这一系列的文章并不是要显示自己的技术 xff0c 而是出于对嵌入式的热爱 非常幸运 xff0c 本人毕业后的十几年一直从事嵌入式行业 xff0c
  • 从零开始构建嵌入式实时操作系统3——任务状态切换

    1 前言 一个行者问老道长 xff1a 您得道前 xff0c 做什么 xff1f 老道长 xff1a 砍柴担水做饭 行者问 xff1a 那得道后呢 xff1f 老道长 xff1a 砍柴担水做饭 行者又问 xff1a 那何谓得道 xff1f
  • 从零开始构建嵌入式实时操作系统4——深入讲解任务切换

    1 前言 操作系统可以为我们执行丰富的应用程序 xff0c 可以同时满足我们的各种使用需要 操作系统之所以能同时完成我们各种需求 xff0c 是因为操作系统能并发执行多个用户的应用程序 事实上除了多核处理器系统中是真正的多任务并行之外 xf
  • Linux启动流程之ROM-CODE

    1 从哪里开始 xff1f 下图是AM335X核心板和功能框图 xff1a AM335X核心板的存储信息如下 xff1a AM335X核心板运行linux系统 xff0c 在这里提出一个问题 xff1a 上电后指令从哪里开始执行 xff1f
  • 全志V3S开发板星光闪烁(linux LED驱动)

    1 前言 本文描述了基于全志V3S开发板的LED驱动程序和测试应用程序的设计流程 通过本次实验我们可以控制V3S电路板上的LED xff0c 模拟星空的星星 xff0c 一闪一闪亮晶晶 xff01 2 设计流程概述 本次实验的设计步骤如下
  • 人脑能否重启?

    1 重启是什么 人脑能否重启 这个问题还不简单 xff0c 人睡眠后清醒就是重启 事实真的是如此简单吗 xff1f 我们先不急着给出结论 xff0c 前面提到 人睡眠后清醒就是重启 xff0c 这句话中有两概念 xff1a 1 睡眠和觉醒
  • 嵌入式技术之IAP,自从有了它老板再也不担心我的代码了!(中)

    上篇文章我们一起学习了IAP的工作原理和IAP包含的3个重要功能 xff1a 数据交互 数据存储和程序跳转 这3个重要功能称为 IAP的三板斧 xff0c 接下来我们看这三板斧具体完成哪些细节工作 xff0c 如何实现这三板斧 1 数据交互
  • 超导量子计算机

    1 超导量子计算机发展状况 2018年3月5日美国物理学会年会上 xff0c 谷歌展示了其正在测试的72量子位超导量子芯片Bristlecone 谷歌物理学家朱利安 凯利表示 xff0c 研讨团队希望初次运用更大的量子芯片来展现霸权 xff
  • Ubuntu 快速更换阿里源

    简介 xff1a 本文主要给大家讲解如何为Ubuntu更换阿里源 xff0c 通过以下四个步骤即可快速实现换源 镜像下载 域名解析 时间同步请点击 阿里巴巴开源镜像站 一 查看ubuntu的Codename lsb release a gr
  • 建造《流浪地球2》中要毁灭人类的超级量子计算机MOSS的核心量子技术是什么?

    1 流浪地球2 中的量子计算机 2023年中国最火的电影非 流浪地球2 莫属 xff0c 在 流浪地球2 中有一个人工智能机器人MOSS xff0c 它的前身是 550W 超级量子计算机 xff0c MOSS 是它给自己起的名字 xff08
  • 离子阱量子计算机

    1 新闻 2020年6月 xff0c 科技制造企业霍尼韦尔 xff08 Honeywell xff09 发布第一台离子阱量子计算机H0 xff0c 它拥有64量子体积 xff0c 它是IBM和谷歌同时期量子计算机的两倍 公司表示之所以能取得
  • ROS Melodic安装、配置和使用turtlebot2(集成众多源代码直接下载)

    已经有前辈将ubuntu14 04下的turtlebot教程翻译了过来 xff0c 可以先行查看 xff0c 对turtlebot的知识建立总体的认识 xff1a https www ncnynl com archives 201609 7
  • FreeRTOS学习 第一讲 操作系统的移植

    FreeRTOS学习 第一讲 操作系统的移植 基本介绍 xff1a 系统分类 1 xff09 前后台系统 while 1 循环 适用情况 xff08 简单和小的需求 处理需求相对来说较少 xff09 2 xff09 实时操作系统 实时操作系
  • Python调用playsound时报错:指定的设备未打开,或不被 MCI 所识别

    报错信息 xff1a Error 263 for command close audio mp3 指定的设备未打开 或不被 MCI 所识别 原因 xff1a windows不支持utf 16编码 xff0c 需修改playsound源码 p
  • 【无人机学习】Mission Planner(pc端)和QGroundControl(android端)

    无人机学习 Mission Planner xff08 pc端 xff09 和QGroundControl xff08 android端 xff09 系列文章目录 提示 xff1a 这里是收集了无人机的相关文章 无人机学习 无人机基础知识

随机推荐

  • 【无人机学习之QGroundControl】android端App初解4-遥控器通道

    无人机学习之QGroundControl android端App初解4 遥控器通道 系列文章目录 提示 xff1a 这里是收集了无人机的相关文章 无人机学习 无人机基础知识 无人机学习 Mission Planner xff08 pc端 x
  • 百度2014校园招聘 软件研发工程师 笔试题

    一 简答题 xff08 本题共30 xff09 1 动态链接库和静态链接库分别有什么优缺点 xff1f xff08 10 xff09 2 轮询任务调度与抢占式任务调度的区别 xff1f xff08 10 xff09 3 请列出数据库中常用的
  • Kubernetes 日志查询分析实践

    简介 xff1a 本文将介绍如何基于日志服务实现对 Kubernetes xff08 以下简称 K8s xff09 日志的采集以及查询分析 xff0c 此外 xff0c 还附带了对 Ingress Audit 方案的简要介绍 为了方便大家通
  • C++算法题

    目录 一 排序算法 1 冒泡排序 2 快速排序 3 归并排序 4 堆排序 5 插入排序 6 topK 二 二分查找 1 一维数组二分查找 2 二维数组二分查找 3 寻找旋转排序数组中的最小值 三 有序数组的平方 xff08 双指针法 xff
  • QT通过UDP分包传输大图像(测试可传6M)

    参考博客 UDP传数据每帧数据最大传64k xff0c 而图片文件一般远大于64K xff0c 此时就需要将图像数据分包传输 xff0c 接收端也分包接收 xff0c 直到整个图片数据都收到 xff0c 再进行其他处理 发送端 发送数据 v
  • github代码如何定位到历史版本(历史commit点)

    关于使用git在本地进行版本管理见linux下的版本管理 工作项目中git流程实操见git简明实操模板 想我们在写代码时候 xff0c 数次修改并提交commit xff0c 如果在这个过程中我们后悔了 xff0c 想回到当初的某一个com
  • Intel RealSense学习之图像及图像深度数据获取

    本文将介绍如何获取到彩色图像的深度信息 大家都知道我们可以从realsense 摄像头中获取到RGB数据 xff0c 红外数据 xff0c 以及图像的深度数据 至于图像的深度数据我的理解是realsense摄像投抓到的图像的相关距离信息 x
  • ROS机器人编程实践——读书笔记1

    目的 xff1a 写一个最小基于ROS的机器人控制软件 一 写一个运动命令流 xff0c 每秒10次 xff0c 每三秒启动一次 在移动时 xff0c 发送前进命令 xff0c 速度0 5米每秒 xff0c 停止时发送速度0米每秒 命名为
  • SLAM后端:因子图优化

    xff08 一 xff09 贝叶斯网络 贝叶斯网络是种概率图 xff0c 由随机变量节点和表达随机变量条件独立性的边组成 xff0c 形成一个有向无环图 在 SLAM 中 由于我们有运动方程和观测方程 它们恰好表示了状态变量之间的条件概率
  • Ceres用法及Ceres-Sophus在位姿图优化问题的应用

    xff08 一 xff09 Ceres Solver的一般用法 简述 xff1a Ceres Solver is an open source C 43 43 library for modeling and solving large c
  • 基于深度卷积神经网络的语义地图构建

    xff08 一 xff09 相关研究及特点 语义分割 语义信息 xff1a 物体类别 目标检测 语义分割等 语义分割即对图像中每个像素分配类别标签 目前最主流的是深度学习方法 xff0c 代表性的方法是全卷积神经网络 xff08 fully
  • 语义信息用于闭环检测

    xff08 一 xff09 SLAM闭环检测方法 传统特征点方法 xff1a 利用SIFT 等视觉特征进行对比闭环检测 受环境影响较大 xff0c 往往会产生假阳性检测 xff0c 且计算量大 效率低 在实际应用上存在较大的阻碍 深层特征方
  • 盘点|2021年最受欢迎Linux桌面操作系统前十名

    简介 xff1a 根据各操作系统镜像站后台下载量 xff0c 阿里云镜像站统计了2021年最受欢迎的Linux桌面操作系统 xff0c 仅根据调用量排名 xff0c 供大家参考 排位最高的还是Centos xff0c 受中国Linux用户欢
  • VSLAM框架对比

    xff08 一 xff09 单目VSLAM特点介绍 xff1a 1 ORB SLAM2 工作流程 xff1a 主要模块 xff1a 前端 xff1a ORB特征提取匹配 xff0c 估计相机位姿 xff1b 根据跟踪地图点数的减少选择关键帧
  • ORB-SLAM3的Euroc数据集测试

    xff08 一 xff09 测试运行 不同模式测试过程 xff08 以MH 03为例 xff09 1 pure mono 运行SLAM xff1a cd ORB SLAM3 Example run slam Monocular mono e
  • 阶段性工作总结

    xff08 一 xff09 简介 1 常用VSLAM开源框架对比 xff0c 初步研究方向确定 2 ORB SLAM3的数据集测试 xff0c 各种模式下的运行性能对比 xff0c 及IMU模式下与Vins对比实验 3 adas视频在ORB
  • 第二阶段文献总结

    xff08 一 xff09 CoSLAM 1 系统功能和亮点 功能 xff1a 本文是第一个动态场景下多相机合作的同时定位 静态图构建 动态点轨迹估计的SLAM系统 亮点 xff1a 引入相机间位姿估计和相机间建图解决动态物体问题维护每一个
  • 第三阶段文献总结

    motion分割相关方法 xff08 一 xff09 Semantic segmentation aided visual odometry for urban autonomous driving 1 文章特点 xff1a VO中包含重投
  • 动态场景SLAM相关论文总结

    参考文献 xff1a VDO SLAM xff08 动物判别与跟踪 xff09 DynaSLAM xff08 深度学习 43 多视图几何分割 xff09 CoFusion xff08 语义 43 运动分割 xff09 Meaningful
  • 算法总结——八皇后问题(三种解法)

    问题描述 会下国际象棋的人都很清楚 xff1a 皇后可以在横 竖 斜线上不限步数地吃掉其他棋子 如何将8个皇后放在棋盘上 xff08 有8 8个方格 xff09 xff0c 使它们谁也不能被吃掉 xff01 这就是著名的八皇后问题 对于某个