N皇后问题(N queen‘s problem)

来源:互联网 发布:全面战争 知乎 编辑:程序博客网 时间:2024/04/29 05:31

N 皇后问题是一个古老而著名的问题, 是回溯算法(back track)的典型案例。问题描述如下:

N x N 的棋盘上放置N个皇后。 要求同一行中, 同一列中, 以及对角线上(包括正负对角线)只能有一个皇后, 否则就会发生clash的情况而失败。 问解决方案?

解决思路如下:

(1)逐列扫描, 从最左边的列开始, 总共有N个queens。

(2)如果所有的queens 都被安全放置了, 就返回true。

(3)对于给定的列, 尝试所有的行, 此时行是变量, 注意此时此列的左边的所有的列都放置了皇后, 此时我们只需要对当前列的所有行进行扫描, 寻找放置的可行的行,所谓可行就是不会与左边的皇后产生clash, 条件为三个方向, 不同列(当然会满足), 不同行, 不同上斜对角线, 不同下斜对角线。 

(4) 一旦放置好当前的列一个的皇后, 就进入下一列放置。 但是一旦没有产生可行解的时候, 就要回溯(backtrack)到上一列, 重新放置上一列的皇后, 继续重复上述步骤, 直至成功, 否则输出失败。

参考程序如下(4 * 4)参考至geeks for geeks:

#include <iostream>#include <cstdio>using namespace std;const int N = 4;// a utility functionvoid printSolution(int board[N][N]) {    for(int i = 0; i < N; ++i) {        for(int j = 0; j < N; ++j) {            cout << board[i][j];        }        cout << endl;    }}// a utility function to chreck if a queen can// be placed on board[row][col], note this function// is called when 'col' queens already placed in columns// from 0 to col - 1, so we need to check only left side// for attacking queensbool isSafe(int board[N][N], int row, int col) {    // check row on left side    for(int i = 0; i < col; ++i) {        if(board[row][i]) {            return false;        }    }    // check upper diagonal on left side    for(int i = row, j = col; i >= 0 && j >= 0; --i, --j) {        if(board[i][j]) {            return false;        }    }    // check lower diagonal on left side    for(int i = row, j = col; i < N && j < col; ++i, --j) {        if(board[i][j]) {            return false;        }    }    return true;}// a recursive utility function to solve N queen// problembool solveNQUtil(int board[N][N], int col) {    // base case: if all queens are placed then return true    if(col >= N) {        return true;    }    // consider this column and try placing this  queen in all rows    // one by one    for(int i = 0; i < N; i++) {        // check if queen can be placed on board        // board[i][col]        if(isSafe(board, i, col)) {            // place this queen on board[i][col]            board[i][col] = 1;            // recur to place the rest of the queens            if(solveNQUtil(board, col + 1) == true) {                return true;            }            // If placing queen on board[i][col] does            // not leads to a solution, we should remove it            board[i][col] = 0; // backtrack        }    }    // If queen cannot be placed in any row    // in this column col, then return false    return false;}bool solveNQ() {    int board[N][N] = {{0, 0, 0, 0}, {0, 0, 0, 0},                       {0, 0, 0, 0}, {0, 0, 0, 0}};    if(solveNQUtil(board, 0) == false) {        cout << "No solution" << endl;        return false;    }    else {        printSolution(board);        return true;    }}// driver programint main() {    solveNQ();    return 0;}
运行结果如下:


参考wiki的http://en.wikibooks.org/wiki/Algorithm_Implementation/Miscellaneous/N-Queens, 如下代码产生所有Nqueen的所有的可行解:

#include <iostream>using namespace std;const int N = 4;int position[N]; // 记录解决方案的N个queen的位置// Check if a position is safebool isSafe(int queen_number, int row_position){ // 检查该行是否安全 // Check each queen before this onefor(int i = 0; i < queen_number; i++){ // 当前queen的左边各列的已经安全的queen// Get another queen's row_positionint other_row_pos = position[i]; // 之前的queen存储的位置在position[i]// Now check if they're in the same row or diagonalsif (other_row_pos == row_position || // Same rowother_row_pos == row_position - (queen_number - i) || // Same diagonalother_row_pos == row_position + (queen_number - i))   // Same diagonalreturn false;}return true;}// Recursively generate a tuple like [0 0 0 0], then [0 0 0 1] then etc...void solve(int k){if (k == N) // We placed N-1 queens (0 included), problem solved!{// Solution found!cout << "Solution: ";for (int i = 0; i < N; i++)cout << position[i] << " ";cout << endl;}else{for (int i = 0; i < N; i++) // Generate ALL combinations{    // 对于当前的k(放置在k列的皇后), 会尝试玩所有的行// Before putting a queen (the k-th queen) into a row, test it for safenessif (isSafe(k, i)) // 可以放即执行下面的语句, 将queen k 放置在位置i处{position[k] = i;// Place another queensolve(k + 1);}}}}int main(){solve(0);return 0;}
运行结果如下:



0 0
原创粉丝点击