8皇后问题详细过程

八皇后问题

在一个8x8的棋盘上,每行每列防止棋子“皇后”,”皇后“不能在同一行,同一列同一条斜线上。
这里写图片描述
对于这个问题通常的做法是:
1. 在一行第一个位置放置一个
2. 遍历第二行,如果找到第一个可放置的位置,则放置,遍历下一行。否则跳转到上一行遍历下一个位置。
3. 一直重复直到所有的位置都被遍历完。
为了便于说明,下面使用4皇后说明。

四皇后坐标
00 01 02 03
10 11 12 13
20 21 22 23
30 31 32 33
22坐标的正对角线坐标和
0
2
22
6
22坐标的负对角线坐标差(x-y)
-2
22
2

可以得出:正对角线坐标和范围为0~(n-1)*2(2为皇后数量),总个数为2n-1,负对角线的差范围-(n-1)~(n-1),总个数为2n-1个。.
对于4皇后问题的解的完整处理过程如下:
这里写图片描述
这里写图片描述
这里写图片描述
代码实现:
n=4 副对角线上的元素为-3~3 为了能处理负数,统一给代码加上n-1,详情查看代码rightDiagonal[row-col+norm]

#include <iostream>
using namespace std;
class ChessBoard{
private:
    const bool available;
    const int squares,norm;                     //norm为了将副对角线差变换到非负数
    bool *column,*leftDiagonal,*rightDiagonal;
    int *positionInRow,howMany;
    void putQueen(int);
    ostream & printBoard(ostream &);
    void initializeBoard();
public:
    ChessBoard();
    ChessBoard(int);
    ~ChessBoard();
    void findSolution();
};
ChessBoard::~ChessBoard() {
    delete [] positionInRow;
    delete [] column;
    delete [] leftDiagonal;
}
ChessBoard::ChessBoard():available(true),squares(8),norm(squares-1){
    initializeBoard();
}
ChessBoard::ChessBoard(int n):available(true),squares(n),norm(squares-1) {
    initializeBoard();
}
void ChessBoard::initializeBoard() {
    int i;
    column = new bool[squares];             //放置行
    positionInRow = new int[squares];       //放置位置
    leftDiagonal = new bool[squares*2-1];   //左边斜线
    rightDiagonal = new bool [squares*2-1]; //右边斜线
    for(i = 0;i<squares;i++)
        positionInRow[i] = -1;
    for(i=0;i<squares;i++)
        column[i] = available;
    for(i=0;i<squares*2-1;i++)
        leftDiagonal[i] = rightDiagonal[i] = available;
    howMany = 0;
}
void ChessBoard::putQueen(int row) {
    cout<<"函数开始:当前行为: "<<row<<"行,遍历不同的列col"<<endl;
    for (int col = 0; col < squares; col++){
        cout<<"for循环:循环开始在"<<row<<"行,"<<col<<"列!"<<endl;

        if(column[col] == available &&leftDiagonal [row+col] == available &&rightDiagonal[row-col+norm] == available) {
            cout<<"判断:经判断"<<col<<"列能放,列放置位置: "<<"("<<row<<","<<col<<")"<<"进入下一行:"<<row+1<<endl;
            //放置皇后在row
            positionInRow[row] = col;
            column[col] = !available;
            leftDiagonal[row+col] = !available;
            rightDiagonal[row-col+norm] = !available;
            if (row < squares-1)
                putQueen(row+1);
            else{
                printBoard(cout);
                howMany+=1;
                cout<<"找到第"<<howMany<<"个结果"<<endl;
            }
            column[col] = available;
            leftDiagonal[row+col] = available;
            rightDiagonal[row-col+norm] = available;
        }
        if(col==squares-1)
        {
            if(row-1>=0)
                cout<<"当前行遍历完成!跳到上一行"<<row-1<<endl;
        }

    }
}
ostream & ChessBoard::printBoard(ostream &os) {
//    cout<<"当前行为: "<<col<<"\n";
    return os;
}
void ChessBoard::findSolution() {
    putQueen(0);
    cout<<"\n";
    cout<<howMany<<" Solutions found.\n";
}

int main() {
    ChessBoard c1(4);
    c1.findSolution();
    return 0;
}

输出如下:

函数开始:当前行为: 0行,遍历不同的列col
for循环:循环开始在0行,0列!
判断:经判断0列能放,列放置位置: (0,0)进入下一行:1
函数开始:当前行为: 1行,遍历不同的列col
for循环:循环开始在1行,0列!
for循环:循环开始在1行,1列!
for循环:循环开始在1行,2列!
判断:经判断2列能放,列放置位置: (1,2)进入下一行:2
函数开始:当前行为: 2行,遍历不同的列col
for循环:循环开始在2行,0列!
for循环:循环开始在2行,1列!
for循环:循环开始在2行,2列!
for循环:循环开始在2行,3列!
当前行遍历完成!跳到上一行1
for循环:循环开始在1行,3列!
判断:经判断3列能放,列放置位置: (1,3)进入下一行:2
函数开始:当前行为: 2行,遍历不同的列col
for循环:循环开始在2行,0列!
for循环:循环开始在2行,1列!
判断:经判断1列能放,列放置位置: (2,1)进入下一行:3
函数开始:当前行为: 3行,遍历不同的列col
for循环:循环开始在3行,0列!
for循环:循环开始在3行,1列!
for循环:循环开始在3行,2列!
for循环:循环开始在3行,3列!
当前行遍历完成!跳到上一行2
for循环:循环开始在2行,2列!
for循环:循环开始在2行,3列!
当前行遍历完成!跳到上一行1
当前行遍历完成!跳到上一行0
for循环:循环开始在0行,1列!
判断:经判断1列能放,列放置位置: (0,1)进入下一行:1
函数开始:当前行为: 1行,遍历不同的列col
for循环:循环开始在1行,0列!
for循环:循环开始在1行,1列!
for循环:循环开始在1行,2列!
for循环:循环开始在1行,3列!
判断:经判断3列能放,列放置位置: (1,3)进入下一行:2
函数开始:当前行为: 2行,遍历不同的列col
for循环:循环开始在2行,0列!
判断:经判断0列能放,列放置位置: (2,0)进入下一行:3
函数开始:当前行为: 3行,遍历不同的列col
for循环:循环开始在3行,0列!
for循环:循环开始在3行,1列!
for循环:循环开始在3行,2列!
判断:经判断2列能放,列放置位置: (3,2)进入下一行:4
找到第1个结果
for循环:循环开始在3行,3列!
当前行遍历完成!跳到上一行2
for循环:循环开始在2行,1列!
for循环:循环开始在2行,2列!
for循环:循环开始在2行,3列!
当前行遍历完成!跳到上一行1
当前行遍历完成!跳到上一行0
for循环:循环开始在0行,2列!
判断:经判断2列能放,列放置位置: (0,2)进入下一行:1
函数开始:当前行为: 1行,遍历不同的列col
for循环:循环开始在1行,0列!
判断:经判断0列能放,列放置位置: (1,0)进入下一行:2
函数开始:当前行为: 2行,遍历不同的列col
for循环:循环开始在2行,0列!
for循环:循环开始在2行,1列!
for循环:循环开始在2行,2列!
for循环:循环开始在2行,3列!
判断:经判断3列能放,列放置位置: (2,3)进入下一行:3
函数开始:当前行为: 3行,遍历不同的列col
for循环:循环开始在3行,0列!
for循环:循环开始在3行,1列!
判断:经判断1列能放,列放置位置: (3,1)进入下一行:4
找到第2个结果
for循环:循环开始在3行,2列!
for循环:循环开始在3行,3列!
当前行遍历完成!跳到上一行2
当前行遍历完成!跳到上一行1
for循环:循环开始在1行,1列!
for循环:循环开始在1行,2列!
for循环:循环开始在1行,3列!
当前行遍历完成!跳到上一行0
for循环:循环开始在0行,3列!
判断:经判断3列能放,列放置位置: (0,3)进入下一行:1
函数开始:当前行为: 1行,遍历不同的列col
for循环:循环开始在1行,0列!
判断:经判断0列能放,列放置位置: (1,0)进入下一行:2
函数开始:当前行为: 2行,遍历不同的列col
for循环:循环开始在2行,0列!
for循环:循环开始在2行,1列!
for循环:循环开始在2行,2列!
判断:经判断2列能放,列放置位置: (2,2)进入下一行:3
函数开始:当前行为: 3行,遍历不同的列col
for循环:循环开始在3行,0列!
for循环:循环开始在3行,1列!
for循环:循环开始在3行,2列!
for循环:循环开始在3行,3列!
当前行遍历完成!跳到上一行2
for循环:循环开始在2行,3列!
当前行遍历完成!跳到上一行1
for循环:循环开始在1行,1列!
判断:经判断1列能放,列放置位置: (1,1)进入下一行:2
函数开始:当前行为: 2行,遍历不同的列col
for循环:循环开始在2行,0列!
for循环:循环开始在2行,1列!
for循环:循环开始在2行,2列!
for循环:循环开始在2行,3列!
当前行遍历完成!跳到上一行1
for循环:循环开始在1行,2列!
for循环:循环开始在1行,3列!
当前行遍历完成!跳到上一行0

猜你喜欢

转载自blog.csdn.net/bleedingfight/article/details/81416976
今日推荐