八皇后问题回溯递归C++实现

对于皇后棋子来说,可以将其所在的行、列、左斜线和右斜线视为其私有领域,不允许其他棋子放在上面。

为将问题简化,首先考虑一个4x4的棋盘,如下图 所示:

(0,0) (0,1) (0,2) (0,3)
(1,0) (1,1) (1,2) (1,3)
(2,0) (2,1) (2,2) (2,3)
(3,0) (3,1) (3,2) (3,3)


可以看到,在表格左面向右上方的斜线方格内横纵坐标之和为0至6,然后可以声明一个下标0-6的bool数组leftDiagonal[6],标记6条左斜线是否可以放置棋子。

同理在表格右边向左上方的对角线的 横纵坐标之差为-3至3,也可以用一个bool数组rightDiagnoal[6]标记这6条对角线是否可以放置棋子,为放置数组下标小于0,将(-3,3)分别加上3表示数组下标。

最后再加上标记棋子所在列的 下标0-4的bool数组cloumn[4],标记该列是否可以放置棋子。

由于是逐行进行放置棋子,所以不用考虑两个棋子在同一行的情况。代码如下所示:

头文件棋盘声明

#ifndef CHESSBOARD_H_
#define CHESSBOARD_H_
#include
using namespace std;

class Chessboard{
public:
	Chessboard();      //8 x 8
	Chessboard(int n); //n x n
	void findSolution();
private:
	const bool avaliable;
	const int square, norm;
	bool *column, *leftDiagonal, *rightDiagonal;
	int *positionInrow, howmany;
	void putqueen(int n);
	void printBoard();
	void initializeBoard();
};

#endif
类的实现cpp

#include"chessboard.h"

Chessboard::Chessboard() : avaliable(true), square(8), norm(square-1)
{
	initializeBoard();
}
Chessboard::Chessboard(int n) : avaliable(true), square(n), norm(square - 1)
{
	initializeBoard();
}

void Chessboard::initializeBoard()
{
	int i = 0;
	column = new bool[square];
	positionInrow = new int[square];
	leftDiagonal = new bool[square * 2 - 1];
	rightDiagonal = new bool[square * 2 - 1];
	for (i = 0; i < square; i++)
	{
		positionInrow[i] = -1;
		column[i] = avaliable;
	}
	for (i = 0; i < 2 * square - 1; i++)
	{
		leftDiagonal[i] = rightDiagonal[i] = avaliable;
	}
	howmany = 0;
}

void Chessboard::printBoard()
{
	for (int i = 0; i < square; i++)
	{
		for (int j = 0; j < square; j++)
		{
			if (j == positionInrow[i])
				cout << "1" << "  ";
			else
				cout << "0"<<"  ";
			
		}
		cout << endl;
	}
	cout << "************" << endl;
}

void Chessboard::putqueen(int row)
{
	for (int col = 0; col < square; col++)
	{
		if (column[col] == avaliable && leftDiagonal[row + col] == avaliable
			&& rightDiagonal[row - col + norm] == avaliable)
		{
			positionInrow[row] = col;
			column[col] = !avaliable;
			leftDiagonal[row + col] = !avaliable;
			rightDiagonal[row - col + norm] = !avaliable;

			if (row < square - 1)
				putqueen(row + 1);
			else
			{
				printBoard();
				howmany++;
			}
			column[col] = avaliable;
			leftDiagonal[row + col] = avaliable;
			rightDiagonal[row - col + norm] = avaliable;
		}
	}
}

void Chessboard::findSolution()
{
	putqueen(0);
	cout << howmany << "  solutions found.\n" << endl;
}
主函数

#include"chessboard.h"

int main()
{
	Chessboard queen(4);
	queen.findSolution();
	return 0;
}

4个棋子时的运行结果

八皇后问题回溯递归C++实现_第1张图片
主要在于putqueen(int)的递归调用,如果第三颗棋子没有找到合适的位置,就会把第二颗棋子标记为不可用的位置标记为可用,然后再寻找下一列一直找到下一个可以放置第二颗棋子的位置,若没有找到可以放置第二颗的位置再修改第一颗棋子标记为不可用的位置重新放置第一颗,若找到放置第二颗棋子的位置则重新寻找第三颗。

你可能感兴趣的:(数据结构,C++,递归,八皇后问题)