N-Queen

N皇后问题。
下面给出一个类,可以解决三个问题:
给定N*N的棋盘,N个皇后。
①得到一个解;
②得到所有解的个数;
③得到所有解。
上述三个问题分别对应类中的函数:
①Return_an_ans;
②Return_all_ans_num;
③Return_all_ans;

注意第一个函数可以返回相当大的解决方案,因为对于第一个问题我们的解决方法是构造法。

class Queen {
public:
    char QChar, BChar;  // 代表皇后和空白的字符
    int * q_in_row;  // q_in_row[i] = j表示在第i行第j列有个皇后
    bool * col_free;  // col_free[i] = true表示第i列没有皇后
    bool * up_free;  // 从右上到左下的对角线是否可以放置皇后
    bool * down_free;  // 从左上到右下的对角线是否可以放置皇后
    int N;  // 皇后个数、正方形棋盘的边长
    bool ONE, NUM, ALL;  // 由于只有一个递归函数,三个变量用于区分是哪一个问题
    bool ONE_FINISH;  // 判断只返回一个解的问题是否已经解决
    int num;  // 所有解的个数
    vector<vector<char> > oneAns;  // 一个解
    vector<vector<vector<char> > > allAns;  // 所有解

    Queen() {
        QChar = 'Q';
        BChar = '.';
        ONE = NUM = ALL = ONE_FINISH = false;
    }

    void changeChar(char q, char b) {  // 可以改变代表皇后和空白的字符
        QChar = q;
        BChar = b;
    }

    void makeBoard(int n) {
        N = n;
        q_in_row = new int[N];
        col_free = new bool[N];
        up_free = new bool[2 * N - 1];
        down_free = new bool[2 * N - 1];
        for (int i = 0; i < N; i++) q_in_row[i] = col_free[i] = true;
        for (int i = 0; i < 2 * N - 1; i++) up_free[i] = down_free[i] = true;
    }

    void deleteBoard() {
        delete []q_in_row;
        delete []col_free;
        delete []up_free;
        delete []down_free;
    }

    void construct_solution() {  // 构造法
        int row = 0;
        if (N % 6 != 2 && N % 6 != 3) {
            if (N % 2 == 0) {
                for (int i = 2; i <= N; i += 2) q_in_row[row++] = i - 1;
                for (int i = 1; i <= N - 1; i += 2) q_in_row[row++] = i - 1;
            } else {
                for (int i = 2; i <= N - 1; i += 2) q_in_row[row++] = i - 1;
                for (int i = 1; i <= N; i += 2) q_in_row[row++] = i - 1;
            }
        } else {
            if (N % 2 == 0) {
                if ((N / 2) % 2 == 0) {
                    for (int i = N / 2; i <= N; i += 2) q_in_row[row++] = i - 1;
                    for (int i = 2; i <= N / 2 - 2; i += 2) q_in_row[row++] = i - 1;
                    for (int i = N / 2 + 3; i <= N - 1; i += 2) q_in_row[row++] = i - 1;
                    for (int i = 1; i <= N / 2 + 1; i += 2) q_in_row[row++] = i - 1;
                } else {
                    for (int i = N / 2; i <= N - 1; i += 2) q_in_row[row++] = i - 1;
                    for (int i = 1; i <= N / 2 - 2; i += 2) q_in_row[row++] = i - 1;
                    for (int i = N / 2 + 3; i <= N; i += 2) q_in_row[row++] = i - 1;
                    for (int i = 2; i <= N / 2 + 1; i += 2) q_in_row[row++] = i - 1;
                }
            } else {
                if ((N / 2) % 2 == 0) {
                    for (int i = N / 2; i <= N - 1; i += 2) q_in_row[row++] = i - 1;
                    for (int i = 2; i <= N / 2 - 2; i += 2) q_in_row[row++] = i - 1;
                    for (int i = N / 2 + 3; i <= N - 2; i += 2) q_in_row[row++] = i - 1;
                    for (int i = 1; i <= N / 2 + 1; i += 2) q_in_row[row++] = i - 1;
                    q_in_row[row++] = N - 1;
                } else {
                    for (int i = N / 2; i <= N - 2; i += 2) q_in_row[row++] = i - 1;
                    for (int i = 1; i <= N / 2 - 2; i += 2) q_in_row[row++] = i - 1;
                    for (int i = N / 2 + 3; i <= N - 1; i += 2) q_in_row[row++] = i - 1;
                    for (int i = 2; i <= N / 2 + 1; i += 2) q_in_row[row++] = i - 1;
                    q_in_row[row++] = N - 1;
                }
            }
        }
        write_in(oneAns);
    }

    vector<vector<char> > Return_an_ans(int n) {
        makeBoard(n);

        if (n > 3) {
            construct_solution();
            deleteBoard();
            return oneAns;
        }

        ONE = true;
        dfs(0);
        deleteBoard();
        return oneAns;
    }

    int Return_all_ans_num(int n) {
        makeBoard(n);
        NUM = true;
        num = 0;
        dfs(0);
        deleteBoard();
        return num;
    }

    vector<vector<vector<char> > > Return_all_ans(int n) {
        makeBoard(n);
        ALL = true;
        dfs(0);
        deleteBoard();
        return allAns;
    }

    void write_in(vector<vector<char> > & a) {
        a.resize(N);
        for (int i = 0; i < N; i++) {
            a[i].resize(N);
            for (int j = 0; j < N; j++) {
                if (q_in_row[i] == j) a[i][j] = QChar;
                else a[i][j] = BChar;
            }
        }
    }

    void dfs(int now) {

        if (now == N) {
            if (ONE) {
                ONE_FINISH = true;
                write_in(oneAns);
                return;
            }
            if (NUM) {
                num++;
                return;
            }
            if (ALL) {
                vector<vector<char> > a;
                write_in(a);
                allAns.push_back(a);
                return;
            }
        }

        for (int col = 0; col < N; col++) {
            if (col_free[col] && up_free[now + col] && down_free[now - col + N - 1]) {
                q_in_row[now] = col;
                col_free[col] = up_free[now + col] = down_free[now - col + N - 1] = false;
                dfs(now + 1);
                if (ONE && ONE_FINISH) return;
                col_free[col] = up_free[now + col] = down_free[now - col + N - 1] = true;
            }
        }
    }
};

附上测试结果:
N-Queen - Night - Time Ends.

N-Queen - Night - Time Ends.
 
N-Queen - Night - Time Ends.
 
N-Queen - Night - Time Ends.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值