八皇后 -- 递归

描述

题目描述
会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题。 对于某个满足要求的8皇后的摆放方法,定义一个皇后串a与之对应,即a=b1b2…b8,其中bi为相应摆法中第i行皇后所处的列数。已经知道8皇后问题一共有92组解(即92个不同的皇后串)。 给出一个数b,要求输出第b个串。串的比较是这样的:皇后串x置于皇后串y之前,当且仅当将x视为整数时比y小。
输入描述:
每组测试数据占1行,包括一个正整数b(1 <= b <= 92)
输出描述:
输出有n行,每行输出对应一个输入。输出应是一个正整数,是对应于b的皇后串。
示例1

输入
1
输出
15863724

分析

首先得找到全部92种排列方式,然后就可以进行排序输出了。
要找到全部方式,就是 经典的八皇后部分
用x[i]表示放在第i行的第x[i]个位置,其中1<=i<=8 1<=x[i]<=8;
初始化x[i]都为0
从第一行开始尝试,如果放在第j列的位置可以的话,就递归的去判断第二行,直到第8行以后,可以输出答案,这里为了便于处理用字符串记录,后面又转化为整数;
判断位置是否合法即当前第k行的x[k]跟前面的x[i],i< k都不相同,也就是不在同一列;
另外abs(k-i)==abs(x[k]-x[i])则判断是否在同以斜线(斜率为1)
可以想象是在回溯的遍历一棵八叉树

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;
vector<string> anss;
vector<long long> nums;
int x[10];
int sum = 0;
bool place(int k)
{
    for (int i = 1; i <k; i++)
        if (x[k] == x[i] || abs(k - i) == abs(x[k] - x[i]))return false;
    return true;
}
void quene(int t)
{
    if (t>8)
    {
        sum++;
        string temp = "";
        for (int i = 1; i <= 8; i++)
        {
            char c = x[i] + '0';
            temp = temp + c;
        }
        //cout << temp << "\n";
        anss.push_back(temp);
    }
    else {
        for (int i = 1; i <= 8; i++)
        {
            x[t] = i;
            if (place(t))quene(t + 1);
        }
    }
}
long long str2ll(string str)
{
    long long sum1 = 0;
    for (int i = 0; i<str.length(); i++)
        sum1 = sum1 * 10 + str[i] - '0';
    return sum1;
}
void sortTheOrder()
{
    //cout << sum << "\n";
    for (int i = 0; i<anss.size(); i++)
        nums.push_back(str2ll(anss[i]));
    sort(nums.begin(), nums.end());
}
int main()
{
    for (int i = 1; i <= 8; i++)x[i] = 0;
    int b;
    quene(1);
    sortTheOrder();
    while (cin >> b)
    {
        cout << nums[b - 1] << "\n";
    }
}
点赞