3472. 八皇后
⭐️难度:中等
⭐️类型:DFS
📖题目:题目链接
会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。
如何将 8个皇后放在棋盘上(有 8×8个方格),使它们谁也不能被吃掉!
这就是著名的八皇后问题。
对于某个满足要求的 8皇后的摆放方法,定义一个皇后串 a与之对应,即 a=b1b2...b8,其中 bi为相应摆法中第 i行皇后所处的列数。
已经知道 8皇后问题一共有 92组解(即 92个不同的皇后串)。
给出一个数 b,要求输出第 b个串。
串的比较是这样的:皇后串 x置于皇后串 y之前,当且仅当将 x视为整数时比 y小。
输入格式
第一行包含整数 n,表示共有 n组测试数据。
每组测试数据占 1 行,包括一个正整数 b。
输出格式
输出有 n行,每行输出对应一个输入。
输出应是一个正整数,是对应于 b的皇后串。
数据范围
1≤b≤92
输入样例:
2
1
92
输出样例:
15863724
84136275
🌟思路:求出92组解
1️⃣法一:DFS
- 用
queenVec存92种答案, - 用
queen存临时解,和 第pos行皇后的列号 i当前要放的列j遍历已经放好的皇后
步骤:
1、每放好一行皇后,递归深入放下一行;
2、放满 8 个,存解;
3、递归返回后,pop_back() 回溯,尝试当前行的下一列;
如何检验皇后位置是否合法?
要对行、列、斜线,进行检验,
- 行:递归时是按行依次放入,所以行不用检验,
cpp
DFS(queen, 0); // 从第0行开始放皇后
- 列:
cpp
queen[j] == i
- queen[j]:第 j 行皇后的列号;
- i:第 pos 行皇后打算放的列号;
如果相等 → 两个皇后在同一列,直接不合法。
- 斜线:
cpp
pos - j == queen[j] - i // 主斜线冲突,例如(0,1)->(1,2)
pos - j == i - queen[j] // 副斜线冲突,例如(0,7)->(1,6)
核心:两坐标的行列之差绝对值相等,
pos-j是行之差,
queen[j]-i i-queen[j]是列之差,
2️⃣法二:打表
因为结果数量很有限,所以可以考虑打表。
把所有结果存在数组中,直接根据输入进行输出。
📚题解:
1️⃣法一
cpp
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<vector> // vector不需要.h
#include<list>
#include<set> // // 可以用 set 和 multiset
#include<unordered_set> // 可以用 unordered_set 和 unordered_multiset
#include<map> // 可以用 map 和 multimap
#include<unordered_map> // 可以用 unordered_map 和 unordered_multimap
#include<algorithm>
#include<string>
#include<iostream>
#include<queue>
#include<stack>
using namespace std;
// 希望所有的函数都能访问 queenVec
vector<vector<int>> queenVec;
void DFS(vector<int>& queen, int pos) {
// 打算放下一个皇后
for (int i = 1;i <= 8; i++) {
// i 就是 第pos号皇后打算放的列
bool flag = true;
for (int j = 0;j < pos;j++) {
// j 就是用来遍历之前已经放好的皇后 0~pos-1
if (queen[j] == i || // 第j号皇后 和 pos皇后 在同一列
pos - j == queen[j] - i ||
pos - j == i - queen[j] // 在一条斜对角线上
) {
flag = false;
}
}
if (flag == true) {
queen.push_back(i); // 将pos号皇后的列数设置好
if (pos == 7) {
// 8个皇后都已经放好了
queenVec.push_back(queen);
}
else {
DFS(queen, pos + 1);
}
queen.pop_back(); // 为下一种i的可能性做准备(前面已经放好的不动,继续探讨多余的可能)
}
}
}
int main() {
vector<int> queen; // 用来记录已经放好的皇后的位置
DFS(queen, 0); // 从第0行开始放皇后
int n;
scanf("%d", &n);
for (int i = 0;i < n;i++) {
int b;
scanf("%d", &b);
vector<int> it = queenVec[b - 1]; //queenVec 从 0 开始存储,应该访问 queenVec[b-1]
for (int i = 0;i < 8;i++) {
printf("%d", it[i]);
}
printf("\n");
}
return 0;
}
2️⃣法二
cpp
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <vector>
#include <string>
using namespace std;
// 希望所有的函数都能访问 queenVec
vector<vector<int>> queenVec; //用来存放所有的合法皇后序列
void DFSFindQueen(vector<int> &queen, int pos) {
// 打算放下一个皇后
for (int i = 1; i <= 8; ++i) {
// i 就是 第pos号皇后打算放的列
bool isOK = true;
for (int j = 0; j < pos; ++j) {
// j就是用来遍历之前已经放好的皇后 0~pos-1
if (queen[j] == i || //第j号皇后 和 pos皇后 在同一列
pos - j == queen[j] - i ||
pos - j == i - queen[j] // 在一条斜对角上
) {
isOK = false;
break;
}
}
if (isOK == true) {
queen.push_back(i); // 将pos号皇后的列数设置好
if (pos == 7) {
// 8个皇后都已经放好了
queenVec.push_back(queen);
printf("\"");
for (int k = 0; k < 8; ++k) {
printf("%d", queen[k]);
}
printf("\",\n");
}
else {
DFSFindQueen(queen, pos + 1);
}
queen.pop_back(); //为下一种i的可能性做准备
}
}
}
vector<string> queenVecNew = {
"15863724",
"16837425",
"17468253",
"17582463",
"24683175",
"25713864",
"25741863",
"26174835",
"26831475",
"27368514",
"27581463",
"28613574",
"31758246",
"35281746",
"35286471",
"35714286",
"35841726",
"36258174",
"36271485",
"36275184",
"36418572",
"36428571",
"36814752",
"36815724",
"36824175",
"37285146",
"37286415",
"38471625",
"41582736",
"41586372",
"42586137",
"42736815",
"42736851",
"42751863",
"42857136",
"42861357",
"46152837",
"46827135",
"46831752",
"47185263",
"47382516",
"47526138",
"47531682",
"48136275",
"48157263",
"48531726",
"51468273",
"51842736",
"51863724",
"52468317",
"52473861",
"52617483",
"52814736",
"53168247",
"53172864",
"53847162",
"57138642",
"57142863",
"57248136",
"57263148",
"57263184",
"57413862",
"58413627",
"58417263",
"61528374",
"62713584",
"62714853",
"63175824",
"63184275",
"63185247",
"63571428",
"63581427",
"63724815",
"63728514",
"63741825",
"64158273",
"64285713",
"64713528",
"64718253",
"68241753",
"71386425",
"72418536",
"72631485",
"73168524",
"73825164",
"74258136",
"74286135",
"75316824",
"82417536",
"82531746",
"83162574",
"84136275"
};
int main() {
//vector<int> queen; // 用来记录已经放好的皇后的位置
//DFSFindQueen(queen, 0);
int n;
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
int b;
scanf("%d", &b);
printf("%s\n", queenVecNew[b - 1].c_str());
}
return 0;
}