N皇后问题及答案解

article/2025/10/13 21:22:11

题目
在一张N∗N的国际象棋棋盘上,放置N个皇后,使得所有皇后都无法互相直接攻击得到,(皇后可以直接攻击到她所在的横行,竖列,斜方向上的棋子),现在输入一个整数N,表示在N∗N的棋盘上放N个皇后,请输出共有多少种使得所有皇后都无法互相直接攻击得到的方案数。 例如下面这样的摆法,是4皇后的一个解 (1代表有皇后,0代表没有)
0 1 0 0
0 0 0 1
1 0 0 0
0 0 1 0

输入
一个整数N,代表皇后的个数

输出
输出方案数

样例输入
样例输入1
4
样例输入2
8

样例输出
样例输出1
2
样例输出2
92

一、DFS+回溯(1)
设已经放好的皇后坐标为(i,j),待放入的皇后坐标为(r,c),则它们满足以下关系:
(1)不同行,即 i ≠ r;
(2)不同列,即 j ≠ c;
(3)不在斜对角线上,即 |i-r| ≠ |j-c|.
可以在一行逐列尝试,这样就不用考虑(1)了。

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int n, tot = 0;
int col[15] = {0}, ans[15] = {0}; //col[i]的值为第i行的皇后的列数的值,即j,ans[]数组用来存放结果bool check(int c, int r) //检查是否和已经放好的皇后冲突
{for (int i = 0; i < r; i++)if (col[i] == c || (abs(col[i] - c) == abs(i - r))) //因为是逐行放置,所以只考虑纵向和斜向return false;return true;
}void dfs(int r,int m)  //在第r行放皇后,m表示行数
{if(r==m){    //r==m,即皇后放到最后一行,满足条件,tot++,返回;tot++;return;}for(int c=0;c<m;c++) //在此行逐列尝试if(check(c,r)){   //检查是否冲突col[r]=c;       //不冲突就在此列放皇后dfs(r+1,m);     //转到下一行继续尝试}
}int main()
{cin>>n;for (int i = 0; i <= 13; i++) //算出所有N皇后的答案,先打表,不然会超时{memset(col, 0, sizeof(col)); //清空col,准备计算下一个N皇后问题tot = 0;dfs(0,i);ans[i] = tot;}cout << ans[n] << endl;return 0;
}

在上述程序中,dfs()一行行放置皇后,时间复杂度为O(N!);check()判断冲突,时间复杂度为O(N),总的为O(N*N!)!非常的高。

二、DFS+回溯(2)

#include <iostream>
#include <algorithm>
using namespace std;int tot = 0, n;
int col[20] = {0}; //col[]含义和上面一样,表示列的值jvoid dfs(int r)
{if (r == n)tot++; //达到递归边界,方案数加一elsefor (int i = 0; i < n; i++){int flag = 1;col[r] = i;                 //尝试把第r行皇后放在第i列for (int j = 0; j < r; j++) //检查是否和前面的皇后冲突if (col[r] == col[j] || r - col[r] == j - col[j] || r + col[r] == j + col[j]){flag = 0;break;}if (flag)dfs(r + 1);}
}int main()
{cin >> n;dfs(0);cout << tot << endl;return 0;
}

优化:
既然皇后是逐行放置的,因此只需要检查纵向和斜向是否攻击即可。纵向好判断,对于斜向,我们可以把格子的坐标设置成(x,y),用(y-x)标识主对角线的值,用(y+x)表示副对角线的值(当然也可以反过来)。这是会发现对于主或副每一条对角线的值是一样且唯一的(其实也不太严谨)。如下图所示:
在这里插入图片描述
在此,我们设置一个二维数组vis[3][2n](为什么是2n接下来会讲到),用vis[0][i]表示i列是否放置皇后,vis[1][r+i](即y+x)表示副对角线是否皇后,用vis[2][r-i+n](即y-x,+n是防止出现负数)表示主对角线是否放置皇后。接下来就简单了,和上面想法一样,对于每一行,从0开始逐列尝试放置皇后,如果在这行的i列中,vis[0][i]和vis[1][r+i]和vis[2][r-i+n]都为零,即这个格子(r,i)的纵向和两个斜向都没有皇后,就在此处放置皇后,并标记这个格子的纵向和两个斜向都已经不能放置皇后(因为这个位置放了新皇后)也就是令vis[0][i] = vis[1][r+i] = vis[2][r-i+n] = 1;继续尝试下一行,最后别忘了取消标记(vis[0][i] = vis[1][r+i] = vis[2][r-i+n] = 0)。

主要思路就是这样,有一些需要注意的细节。因为r-i+n的值最大会达到2n-1,所以最少要设置vis[3][2n],当然大一点会更好。还有就是细心的同学会发现在上面的主对角线中,y-x+n后会有不同的对角线有相同值,其实不用太在意,因为判断条件是同时判断三个(纵向和两个斜向),而对于每一个格子,其三向坐标是唯一的(y,y-x(+n),y+x)。

下面是代码:

#include <iostream>
#include <algorithm>
using namespace std;
int vis[3][45]={0},c[20]={0},tot=0,n; //c[i]表示在i行皇后放置的列的值j,主要为了打印结果;vis[3][]是用来判断的数组,tot存放答案void dfs(int r)
{if(r==n) tot++;  //递归边界,走到最后一行说明方案可行,tot++else for(int i=0;i<n;i++){   //在r行逐列尝试放皇后if(!vis[0][i] && !vis[1][r+i] && !vis[2][r-i+n]){ //如果(r,i)格子的三个方向都没有皇后c[r] = i; //在i列放置皇后,如果不用打印解,可以省略整个c[]vis[0][i] = vis[1][r+i] = vis[2][r-i+n] = 1; //标记dfs(r+1);  //向下一行尝试vis[0][i] = vis[1][r+i] = vis[2][r-i+n] = 0; //取消标记}}
}int main()
{cin>>n;dfs(0);cout<<tot<<endl;return 0;
}

三、
PS:看到还有大佬是用动态规划、公式甚至是位运算做的,以后有空再研究吧,先挖坑。

四、N皇后的一些解
n solution(n)
1 1
2 0
3 0
4 2
5 10
6 4
7 40
8 92
9 352
10 724
11 2680
12 14200
13 73712
14 365596
15 2279184
16 14772512
17 95815104
18 666090624
19 4968057848
20 39029188884
21 314666222712
22 2691008701644
23 24233937684440
24 227514171973736
25 2207893435808352


http://chatgpt.dhexx.cn/article/cDYia82l.shtml

相关文章

N皇后问题递归求解(内附详细代码)

N皇后问题递归求解&#xff08;内附详细代码&#xff09; 内容描述 在n*n的方格棋盘上&#xff0c;放置n个皇后&#xff0c;要求每个皇后不同行、不同列、不同对角线。 解题思路 下面我们以4皇后问题举例&#xff1a; 设queen(i&#xff0c;n)是在1&#xff5e;i-1行上已经放…

八皇后 N皇后

参考打蓝桥杯的通信人 如侵删 所有代码与原博主的代码相似 自作主张的觉着数组设置的太多辽想着改一下代码 写了一个set函数起初简单的认为 把每一个数组元素设置为0 1即可 跑起来后发现有错误 后来修改发现可以设置数组元素 x 只要在同行列或者对角线就会1 符合多个条件就会再…

n皇后学习

洛谷P1219 回溯 #include<cstdio> const int N 13; int n, cnt, ans[N]; void dfs(int row) {if (row n) {if (cnt < 3) {for (int i 0; i < n; i) {if (i > 0)printf(" ");printf("%d", ans[i] 1);}printf("\n");}cnt;ret…

N皇后(回溯算法)

题目 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。等价于要求任何两个皇后都不能在同一行、同一列以及同一条斜线上 给你一个整数 n &#xff0c;返回所有不同的 n 皇后问题 的解决方案。 如图&#xff1a;黄色代表放…

求解n皇后

要求&#xff1a;在国际象棋上摆放n个皇后&#xff0c;使其不能互相攻击&#xff0c;即任意两个皇后都不能处于同一行、同一列或同一斜线上&#xff0c;问有多少种摆法 思路&#xff1a;很直观的想法就是在棋盘上一个一个皇后的摆&#xff0c;如果冲突&#xff0c;则摆放在另一…

n皇后 - 位运算版

n皇后问题是大家在递归里会碰到的一个经典问题。以前高中我学DFS的时候&#xff0c;老师首先让我看的就是八皇后。 不过这皇后的时间复杂度大家可想而知了。而接下来的位运算将这个效率重新提到一个高度。 我是以前在Matrix67大牛那里学的&#xff0c;最近数据结构实验刚好碰到…

n皇后最快算法详解

n皇后问题再经典不过了&#xff0c;想必大家也听说过。 再简单说一下吧&#xff0c;就是一个n*n的棋盘&#xff0c;放置n个皇后&#xff0c;使得竖着不攻击&#xff0c;横着不攻击&#xff0c;斜着不攻击。求有多少种方法。 &#xff08;国际象棋不是这么玩的呀 &#xff09; …

51. N 皇后

51. N 皇后 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整数 n &#xff0c;返回所有不同的 n 皇后问题 的解决方…

51. N皇后

51. N皇后 https://leetcode-cn.com/problems/n-queens/ 四皇后的解 n个皇后&#xff0c; nn 的棋盘上 根据要求 每行有且仅有一个皇后&#xff08;如果有一行没有那么必有一行至少两个皇后&#xff0c;不符合&#xff09; 递归回溯&#xff0c;每次尝试在一行中摆放皇后&…

递归算法——n皇后

** 递归算法——n皇后 ** n皇后问题&#xff1a; 输入整数n&#xff0c;要求n个国际象棋的皇后&#xff0c;摆在n*n的棋盘上&#xff0c;互相不能攻击&#xff0c;输出全部方案。 输入&#xff1a; 输入一个正整数N。 输出&#xff1a; 程序输出N皇后问题的全部摆法。 行里…

kettle连接mysql教程_KETTLE初学者使用教程

Kettle的建立数据库连接、使用kettle进行简单的全量对比插入更新:kettle会自动对比用户设置的对比字段,若目标表不存在该字段,则新插入该条记录。若存在,则更新。 Kettle简介:Kettle是一款国外开源的ETL工具,纯java编写,可以在Window、Linux、Unix上运行,数据抽取高效稳…

Kettle Spoon 安装配置详解

文章目录 1 概述2 安装2.1 软件下载2.2 JDK 环境变量配置2.3 数据库驱动包下载2.4 双击 Spoon.bat 启动 3 简单使用3.1 transformation 转换3.1.1 文件 - 新建 - 转换3.1.2 核心对象 - 输入 - 表输入3.1.3 核对对象 - 输出 - 插入/更新3.1.4 保存 - xxx.ktr 3.2 job 作业3.2.1 …

Spoon安装步骤

主数据库连接步骤 主对象树点击转换&#xff0c;双击DB连接 配置信息完成后点击测试成功 二&#xff0e;源数据库连接步骤 1.点击Connect,点击other repositories 2.点击Database Repository 编辑名称&#xff08;注意必须用英文&#xff09; 再点击数据库连接 配置选项 …

kettle下载安装使用教程

Kettle简介 Kettle是一款国外开源的ETL工具&#xff0c;纯java编写&#xff0c;可以在Window、Linux、Unix上运行&#xff0c; 数据抽取高效稳定。Kettle 中文名称叫水壶&#xff0c;该项目的主程序员MATT 希望把各种数据放到一个壶里&#xff0c;然后以一种指定的格式流出。K…

KETTLE使用教程

Kettle的建立数据库连接、使用kettle进行简单的全量对比插入更新&#xff1a;kettle会自动对比用户设置的对比字段&#xff0c;若目标表不存在该字段&#xff0c;则新插入该条记录。若存在&#xff0c;则更新。 Kettle简介&#xff1a;Kettle是一款国外开源的ETL工具&#xff0…

spoon mysql教程_kettle 教程(一):简介及入门

介绍 kettle 是纯 java 开发&#xff0c;开源的 ETL工具&#xff0c;用于数据库间的数据迁移 。可以在 Linux、windows、unix 中运行。有图形界面&#xff0c;也有命令脚本还可以二次开发。 安装 这边以 windows 下的配置为例&#xff0c;linux 下配置类似。 jdk 安装及配置环境…

kettle基础使用教程

文章目录 前言一、下载、安装二、启动软件三、转换的使用教程四、作业的使用教程总结 前言 Kettle简介&#xff1a;Kettle是一款国外开源的ETL工具&#xff0c;纯java编写&#xff0c;可以在Window、Linux、Unix上运行&#xff0c;数据抽取高效稳定。Kettle 中文名称叫水壶&…

ETL工具-Kettle Spoon教程

转自&#xff1a;https://blog.csdn.net/liaomin416100569/article/details/82798879 一 。Kettle Spoon简介 ETL&#xff08;Extract-Transform-Load的缩写&#xff0c;即数据抽取、转换、装载的过程&#xff09;&#xff0c;对于企业或行业应用来说&#xff0c;我们经常会遇…

KETTLE 使用教程

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Kettle的建立数据库连接、使用kettle进行简单的全量对比插入更新&#xff1a;kettle会自动对比用户设置的对比字段&#xff0c;若目标表…

spoon mysql教程_Kettle-Spoon入门示例

Spoon 是Kettle的设计调试工具 1.驱动: a) 驱动错误 b) 驱动添加 2.端口错误&#xff1a;连接数据库端口不对 3.正常连接 4.表输入 a) 新建一个表输入&#xff0c;获取数据库表的数据 b) 预览数据 c) 当前表数据输出到另外一个同样的表 d) 当前表数据输出到另外一个同样的表 e)…