洛谷P1219 [USACO1.5] 八皇后【n皇后问题】【深搜+回溯 经典题】【附O(1)方法】

P1219 [USACO1.5] 八皇后 Checker Challenge

  • 前言
  • 题目
    • 题目描述
    • 输入格式
    • 输出格式
    • 样例 #1
      • 样例输入 #1
      • 样例输出 #1
    • 提示
    • 题目分析
    • 注意事项
  • 代码
    • 深搜+回溯
    • 打表
  • 后话
    • 额外测试用例
      • 样例输入 #2
      • 样例输出 #2
    • 王婆卖瓜
  • 题目来源

前言

也是说到做到,来做搜索的题(虽然有点拖,但是无伤大雅)。
八皇后,经典的搜索和回溯题,只要学数据结构或者算法基本都会拿出来讲上一嘴或者做一做。想当年说数据结构时对深搜还不太明白,但是学算法时竟然没有看任何提示和题解就自己把n皇后做出来了,当时就很高兴,感觉自己进步了很多。
现在我们就来重温一下这道经典的题目吧!

题目

题目描述

一个如下的 6 × 6 6 \times 6 6×6 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。

上面的布局可以用序列 2   4   6   1   3   5 2\ 4\ 6\ 1\ 3\ 5 2 4 6 1 3 5 来描述,第 i i i 个数字表示在第 i i i 行的相应位置有一个棋子,如下:

行号 1   2   3   4   5   6 1\ 2\ 3\ 4\ 5\ 6 1 2 3 4 5 6

列号 2   4   6   1   3   5 2\ 4\ 6\ 1\ 3\ 5 2 4 6 1 3 5

这只是棋子放置的一个解。请编一个程序找出所有棋子放置的解。
并把它们以上面的序列方法输出,解按字典顺序排列。
请输出前 3 3 3 个解。最后一行是解的总个数。

输入格式

一行一个正整数 n n n,表示棋盘是 n × n n \times n n×n 大小的。

输出格式

前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。

样例 #1

样例输入 #1

6

样例输出 #1

2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4

提示

【数据范围】
对于 100 % 100\% 100% 的数据, 6 ≤ n ≤ 13 6 \le n \le 13 6n13

题目翻译来自NOCOW。

题目分析

  很容易想到使用深搜+回溯,或者换简单来说,使用递归的方法,每层递归就对应一行,一行一行下来,到达最后一行都可行就在统计上加一。然后我们就需要确定哪个点是可行点。
  难点就在对对角线的判断。新的皇后是点(index,i),我们要判断他和上面任意一个皇后(j,queen[j])不在同一条对角线上,那么就是既不在y=x+a上,也不在y=-x+a上,我们可以发现第一条线y-x和第二条线y+x都恒等于a,所以只要不相等那么就是不在同一条对角线上。所以就有了`queen[j]+j!=i+index&&queen[j]-j!=i-index``
  但是这样复杂度还是有点高呢,因为想要判断与上述所有行能否符合条件,所以过不了最后一个点。需要想出一个方法既然判断符合又只需要判断一次。
  所以我们需要转变思路,本来是每一行的每一个点都需要都要与前面的比较,现在我们想能不能在每个点确定以后就更新一份数组(白名单),使得可以让下次选点在白名单内的就是可行的,于是我们需要确定三个数组,一个是竖列,其他两个是他的向左下和右下的对角线。
然后就拿下了

注意事项

1.只输出前三个解
2.数组开大一些,不要像我只开了13,-_-
3.记得恢复现场(深搜必备注意事项)

代码

深搜+回溯

耶

#include<iostream>
#include<algorithm>
#define MaxN  13//n皇后的最大值 
using namespace std;
int queen[MaxN+1]={0},n,total=0;
int a[25]={0},b[25]={0},c[25]={0};
void printqueen(int queen[MaxN+1]) //打印
{
	for(int i = 1 ; i <= n; i++) {
		cout<<queen[i]<<" ";
	}
	cout<<endl;

}
void dfs(int index) //没有return因为并不是每个dfs都会进入下一层
{
	if(index==n+1) { //说明已经完成n行,可以计数了
		total++;
		if(total<=3)//前三个才打印
			printqueen(queen);
		return;
	}
	for(int i = 1; i <= n ; i++) {
			if(!a[i]&&!b[index+i]&&!c[index-i+n]) {
				queen[index]=i;//存储
				a[i]=1;
				b[index+i]=1;
				c[index-i+n]=1; 
				dfs(index+1);//进入下一层
				a[i]=0;//恢复 
				b[index+i]=0;
				c[index-i+n]=0;
		}
	}

}

int main()
{
	cin>>n;
	dfs(1);//从第一层开始
	cout<<total;
	return 0;
}

打表

想不到还有打表吧,哈哈哈。确实有时候很难想到

#include<iostream>
using namespace std;
int main()
{
	int n;
	cin>>n;
	if(n==6) //打表进行中......
	{
		puts("2 4 6 1 3 5");
		puts("3 6 2 5 1 4");
		puts("4 1 5 2 6 3");
		puts("4");
	}
	if(n==7)
	{
		puts("1 3 5 7 2 4 6");
		puts("1 4 7 3 6 2 5");
		puts("1 5 2 6 3 7 4");
		puts("40");
	}
	if(n==8)
	{
		puts("1 5 8 6 3 7 2 4");
		puts("1 6 8 3 7 4 2 5");
		puts("1 7 4 6 8 2 5 3");
		puts("92");
	}
	if(n==9)
	{
		puts("1 3 6 8 2 4 9 7 5");
		puts("1 3 7 2 8 5 9 4 6");
		puts("1 3 8 6 9 2 5 7 4");
		puts("352");
	}
	if(n==10)
	{
		puts("1 3 6 8 10 5 9 2 4 7");
		puts("1 3 6 9 7 10 4 2 5 8");
		puts("1 3 6 9 7 10 4 2 8 5");
		puts("724");
	}
	if(n==11)
	{
		puts("1 3 5 7 9 11 2 4 6 8 10");
		puts("1 3 6 9 2 8 11 4 7 5 10");
		puts("1 3 7 9 4 2 10 6 11 5 8");
		puts("2680");
	}
	if(n==12)
	{
		puts("1 3 5 8 10 12 6 11 2 7 9 4");
		puts("1 3 5 10 8 11 2 12 6 9 7 4");
		puts("1 3 5 10 8 11 2 12 7 9 4 6");
		puts("14200");
	}
	if(n==13)
	{
		puts("1 3 5 2 9 12 10 13 4 6 8 11 7");
		puts("1 3 5 7 9 11 13 2 4 6 8 10 12");
		puts("1 3 5 7 12 10 13 6 4 2 8 11 9");
		puts("73712");
	}
	return 0;
}

后话

额外测试用例

样例输入 #2

13

样例输出 #2

1 3 5 2 9 12 10 13 4 6 8 11 7
1 3 5 7 9 11 13 2 4 6 8 10 12
1 3 5 7 12 10 13 6 4 2 8 11 9
73712

王婆卖瓜

感觉有收获或者想跟上我的进度刷题的,可以点个关注,或者点赞收藏评论都可以!

题目来源

USACO Training Section 1.5
洛谷链接

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

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

相关文章

外汇天眼:外汇市场中的点差是什么? 又该怎么计算呢?

今天为大家揭开外汇点差的神秘面纱&#xff0c;了解这一外汇交易的核心概念。 定义 外汇点差&#xff0c;简单来说&#xff0c;就是外汇市场上买卖双方报价的差异。 每一笔交易由买卖报价中高低不同的部分构成&#xff0c;高出的部分是买方的盈利&#xff0c;低出的部分则是卖…

一文掌握 Spring Boot 常用注解,保姆级整理,建议收藏!

亲兄弟篇&#xff1a; SpringBoot注解大全&#xff08;超详细&#xff09;_Maiko Star的博客-CSDN博客 一、SpringBoot常用注解 二、Bean处理注解 2.1 Resource 依赖注入&#xff0c;自动导入标注的对象到当前类中&#xff0c;比如我们的 Controller 类通常要导入 Service 类…

【Unity】EventSystem.current.IsPointerOverGameObject()对碰撞体起作用

本来我是用 EventSystem.current.IsPointerOverGameObject()来检测是否点击在UI上的&#xff0c;但是发现&#xff0c;他对我的碰撞体也是返回ture,研究半天。。。。找不出问题&#xff0c;然后发现我的相机上挂载了PhysicsRaycaster&#xff0c;去掉之后就好了&#xff0c;至于…

王道操作系统大题汇总(纯手写版,思路过程详细)

文章目录 前言&#xff1a;一、计算机系统概述二、进程与线程三、内存管理四、文件管理五、输入/输出&#xff08;I/0&#xff09;管理 前言&#xff1a; 本文为笔者自用操作系统大题复习&#xff0c;大家可以作为学习的参考&#xff0c;文章只收录操作系统常考大题&#xff0…

Django之cookie和session

文章目录 Cookie的介绍Cookie的由来什么是CookieCookie原理Cookie覆盖浏览器查看Cookie 在Django中操作Cookie设置Cookie查询浏览器携带的Cookie删除Cookie Cookie校验登录sessionSession的由来Session设置查看、更新Session值删除Session值Seesion的其他方法Session的其他配置…

安全牛《数据分类分级自动化建设指南》发布|美创入选代表厂商,分享智能化探索

近日&#xff0c;安全牛发布《数据分类分级自动化建设指南》研究报告&#xff0c;对数据分类分级的主要技术、实施要点、选型指导、发展趋势等展开深入探讨&#xff0c;为各行业数据分类分级自动化工作落地提供帮助与指引。 美创科技被列为代表推荐厂商&#xff0c;落地案例—农…

C++初阶 | [五] 内存管理

摘要&#xff1a;new and delete&#xff0c;定位new&#xff0c;&#xff08;C内存管理的方式&#xff09;&#xff0c;malloc/free和new/delete的区别&#xff0c;内存泄漏 关于内存&#xff1a; 栈又叫堆栈——非静态局部变量/函数参数/返回值等等&#xff0c;栈是向下增长…

JAVA爬虫2 - Jsoup解析、对接MySQL、多线程爬虫、json库使用

官网:https://jsoup.org/download Jsoup是一款基于Java的HTML解析器,它可以方便地从网页中抓取和解析数据。它的主要作用是帮助开 发者处理HTML文档,提取所需的数据或信息。下面介绍几个常用的API: 选择器(Selector)API:用于根据CSS选择器语法选择HTML元素。 属性(Attribute…

深入了解前馈网络、CNN、RNN 和 Hugging Face 的 Transformer 技术!

一、说明 本篇在此对自然语言模型做一个简短总结&#xff0c;从CNN\RNN\变形金刚&#xff0c;和抱脸的变形金刚库说起。 二、基本前馈神经网络&#xff1a; 让我们分解一个基本的前馈神经网络&#xff0c;也称为多层感知器&#xff08;MLP&#xff09;。此代码示例将&#xff1…

Docker | Docker入门安装

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a;Docker系列 ✨特色专栏&#xff1a; My…

STM32-SPI协议详解及CubeMX+HAL函数配置分析

1 SPI协议 SPI(Serial Peripheral interface)串行外围设备接口是同步全双工的通信总线,在芯片的管脚上只占用四根线。 1.1 物理层 SS/NSS/CS:从设备选择信号线(片选信号线)。由主设备控制,选择指定的从设备。 当主机要选择从设备时,把该从设备的SS信号线设置为低电平…

再探MDG cloud-ready模式!看未来MDG的发展路线

紧跟上一篇博客&#xff0c;我们将更加深入探讨一些MDG Cloud-Ready模式的相关内容。 背景 在2021年9月&#xff0c;Harald Kuck&#xff0c;SAP ABAP Platform老大&#xff0c;介绍了未来ABAP的发展路线&#xff0c;并最终在一年后正式推出了ABAP Cloud。他在会上是这么说的…

指针操作一维数组和二维数组的理解!

指针操作一维数组和二维数组的理解&#xff01; 一维数组二维数组 一维数组 你虽然觉得指针操作一维数组很简单&#xff0c;但是通过做题发现并没有那么简单&#xff0c;特别是二维数组&#xff01;&#xff01;&#xff01;   int main() {//创建一维数组int arr[10] { 0,1…

可以在uni-app使用的类vconsole.js插件

兴致勃勃在uni-app项目引入调试工具vconsole.js结果真机调试页面空白 怎么办?! 别着急 paradox老师有方法 替代插件下载地址&#xff1a;直接下载插件并引入HbuilderXuni_modules插件 - 类Vconsole APP端调试工具 - HF调试器 - DCloud 插件市场 下载完成在main.js中引入&…

这样写Allure生成测试报告,学会直接涨薪5k

Allure是一个开源的测试报告生成框架&#xff0c;提供了测试报告定制化功能&#xff0c;相较于我们之前使用过pytest-html插件生成的html格式的测试报告&#xff0c;通过Allure生成的报告更加规范、清晰、美观。 pytest框架支持使用Allure生成测试报告&#xff0c;接下来让介绍…

机器学习算法——聚类算法

目录 1. 概述2. K-MEANS算法2.1 工作流程2.2 代码实践 1. 概述 聚类算法是一种无监督学习方法&#xff0c;用于将数据集中的对象分组或聚集成具有相似特征的集合&#xff0c;该集合被称为簇(cluster)。聚类算法通过计算数据点之间的相似性或距离&#xff0c;将相似的数据点归为…

企业建数仓的第一步是选择一个好用的ETL工具

当企业决定建立数据仓库&#xff08;Data Warehouse&#xff09;&#xff0c;第一步就是选择一款优秀的ETL&#xff08;Extract, Transform, Load&#xff09;工具。数据仓库是企业数据管理的核心&#xff0c;它存储、整合并管理各种数据&#xff0c;为商业决策和数据分析提供支…

java中BigDecimal的介绍及使用(二)

系列文章目录 java中BigDecimal的介绍及使用&#xff0c;BigDecimal格式化&#xff0c;BigDecimal常见问题java中BigDecimal的介绍及使用(二) 文章目录 系列文章目录一、前言二、BigDecimal提供的方法2.1、stripTrailingZeros() 去除小数尾部所有的02.2、int signum()2.3、int…

python爬虫中 HTTP 到 HTTPS 的自动转换

前言 在当今互联网世界中&#xff0c;随着网络安全的重要性日益增加&#xff0c;越来越多的网站采用了 HTTPS 协议来保护用户数据的安全。然而&#xff0c;许多网站仍然支持 HTTP 协议&#xff0c;这就给我们的网络爬虫项目带来了一些挑战。为了应对这种情况&#xff0c;我们需…

vue3的单组件的编写(三)【响应式 API 之 toRef 与 toRefs】

响应式 API 之 toRef 与 toRefs 前面讲了 ref 和 reactive 这两种响应式API &#xff0c;为了方便开发者使用&#xff0c;vue3 还出了两个用来 reactive 转换为 ref 的API&#xff0c;分别是 toRef 和 toRefs 。 &#x1f308;什么是toRef 与 toRefs 这两个API看拼写能猜到&…