[codeup] 2046 八皇后

題目描述

會下國際象棋的人都很清楚:皇后可以在橫、豎、斜線上不限步數地吃掉其他棋子。如何將8個皇后放在棋盤上(有8 * 8個方格),使它們誰也不能被吃掉!這就是著名的八皇后問題。
對於某個滿足要求的8皇后的擺放方法,定義一個皇后串a與之對應,即a=b1b2...b8,其中bi爲相應擺法中第i行皇后所處的列數。已經知道8皇后問題一共有92組解(即92個不同的皇后串)。
給出一個數b,要求輸出第b個串。串的比較是這樣的:皇后串x置於皇后串y之前,當且僅當將x視爲整數時比y小。

輸入

第1行是測試數據的組數n,後面跟着n行輸入。每組測試數據佔1行,包括一個正整數b(1 <= b <= 92)

輸出

輸出有n行,每行輸出對應一個輸入。輸出應是一個正整數,是對應於b的皇后串。

樣例輸入

3
6
4
25

樣例輸出

25713864
17582463
36824175

思路

八皇后問題的答案有92個,首先按照字典序生成這92個答案,然後根據下標查詢即可。生成八皇后直接按行的順序生成八個全排列,這八個全排列即爲八行中每行皇后的位置,也就是列號,然後檢查滿足限制條件即可。

簡單的暴力生成版本:

int count = 0;
int n, p[maxn];
bool hash_table[maxn] = {false};

void generate_p(int index)
{
    if (index == n + 1) { // 判斷全排列滿足條件
        bool flag = true;
        for (int i = 1; i <= n; i++) {
            for (int j = i + 1; j <= n; j++) {
                if (abs(i - j) == abs(p[i] - p[j]))
                    flag = false;
            }
        }
        if (flag)
            count++;
        return;
    }
    for (int x = 1; x <= n; x++) {
        if (hash_table[x] == false) {
            p[index] = x;
            hash_table[x] = true;
            generate_p(index + 1);
            hash_table[x] = false;
        }
    }
}

由於某些全排列序列在前幾個數出來時就可以判斷是錯誤答案了,所以可以稍微優化以下代碼,加上剪枝回溯的版本:

int count = 0;
int n, p[maxn];
bool hash_table[maxn] = {false};

void generate_p(int index)
{
    if (index == n + 1) {
        count++;
        return;
    }
    for (int x = 1; x <= n; x++) {
        if (hash_table[x] == false) {
            bool flag = true; // 剪枝
            for (int pre = 1; pre < index; pre++) {
                if (abs(index - pre) == abs(x - p[pre])) {
                    flag = false;
                    break;
                }
            }
            if (flag == true) {
                p[index] = x;
                hash_table[x] = true;
                generate_p(index + 1);
                hash_table[x] = false;
            }
        }
    }
}

代碼

#include <cstdio>
#include <algorithm>

const int maxn = 11;

int n, p[maxn];
bool hash_table[maxn] = {false};

int count = 0;
int solve[100] = {0};

void generate_p(int index)
{
    if (index == n + 1) {
        count++;
        int tmp = 0;
        for (int i = 1; i <= n; i++) {
            tmp = tmp * 10 + p[i];
        }
        solve[count] = tmp;
        return;
    }
    for (int x = 1; x <= n; x++) {
        if (hash_table[x] == false) {
            bool flag = true;
            for (int pre = 1; pre < index; pre++) {
                if (abs(index - pre) == abs(x - p[pre])) {
                    flag = false;
                    break;
                }
            }
            if (flag == true) {
                p[index] = x;
                hash_table[x] = true;
                generate_p(index + 1);
                hash_table[x] = false;
            }
        }
    }
}

int main()
{
    int m, t;

    n = 8;
    generate_p(1);

    scanf("%d", &m);
    while (m--) {
        scanf("%d", &t);
        printf("%d\n", solve[t]);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章