3472. 八皇后(北京大学考研机试题目)

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() 回溯,尝试当前行的下一列;

如何检验皇后位置是否合法?

要对行、列、斜线,进行检验,

  1. 行:递归时是按行依次放入,所以行不用检验,
cpp 复制代码
DFS(queen, 0); // 从第0行开始放皇后
  1. 列:
cpp 复制代码
queen[j] == i
  • queen[j]:第 j 行皇后的列号;
  • i:第 pos 行皇后打算放的列号;

如果相等 → 两个皇后在同一列,直接不合法。

  1. 斜线:
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;
}
相关推荐
岛雨QA2 小时前
递归「Java数据结构与算法学习笔记5」
数据结构·算法
kebijuelun2 小时前
Learning Personalized Agents from Human Feedback:用人类反馈训练可持续个性化智能体
人工智能·深度学习·算法·transformer
Eloudy2 小时前
稀疏矩阵的 CSR 格式(Compressed Sparse Row)
人工智能·算法·arch·hpc
岛雨QA2 小时前
栈「Java数据结构与算法学习笔记4」
数据结构·算法
乐观勇敢坚强的老彭3 小时前
c++寒假营day05
开发语言·c++·算法
重生之后端学习3 小时前
74. 搜索二维矩阵
开发语言·数据结构·算法·职场和发展·深度优先
JYeontu3 小时前
程序员都该掌握的“质因数分解”
前端·javascript·算法
with-the-flow3 小时前
从数学底层的底层原理来讲 random 的函数是怎么实现的
c语言·python·算法
tyb3333333 小时前
leetcode:吃苹果和队列
算法·leetcode·职场和发展