八皇后问题-递归求解

10 篇文章 0 订阅
8 篇文章 0 订阅

八皇后问题

在国际象棋的棋盘上,按照国际象棋的规则,摆放8个皇后,使之“和平共处”。如图所示,在3-D上有一个皇后,则绿色区域中都不能再放置皇后了。
最暴力的方法就是使用八个for,但是很明显,这种方法效率太低。
在这里插入图片描述
对于放置了皇后的位置,仔细观察棋盘可以发现每一列(行)只能有一个皇后,每一个主(次)对角线上也只能有一个皇后,这样需要标记:行-row,列-col,主对角线-(n+row-col),次对角线-(row+col)

注意:关于对角线的一点说明:
    这里以次对角线为例:数字相同的表示一条次对角线,所以对于一个8x8的棋盘来说,一共有2x8-1条次对角线。
在这里插入图片描述
流程图:
在这里插入图片描述
基于流程图,利用递归的思想,c++实现如下,这里的皇后的个数是在主函数中设置的8,个数可以改,但意义不大。。。。。
在递归回溯的过程中清空了标记,是为了继续搜索,找到所有的解。

#include <iostream>
#include <vector>

using namespace std;

class EightQueen {
public:
	EightQueen(int nQueen) {
		this->nQueen = nQueen;
		inColumn.resize(nQueen, false);
		mainDiagonal.resize(2 * nQueen - 1, false);
		minorDiagonal.resize(2 * nQueen - 1, false);
	}
	~EightQueen() {}
	int process() {
		int *path = new int[nQueen];
		calculate(path, 0);
		delete[] path;
		return 0;
	} 
	void calculate(int *path, int row) {
		if (row == nQueen) {
			solution.push_back(vector<int>(path, path + nQueen));
			return;
		}
		for (int col = 0; col < nQueen; col++) {
			if (canLay(row, col)) {//当前位置可放置
				path[row] = col;//标记放置的位置
				inColumn[col] = true;//当前皇后所在列
				minorDiagonal[row+col] = true;//皇后所在位置的横纵坐标之和对应的次对角线
				mainDiagonal[nQueen-1+row-col] = true;//皇后所在位置的横纵坐标之和对应的主对角线
				calculate(path, row + 1);//下一行上的皇后
				//break;//去掉搜索所有的解!
				inColumn[col] = false;
				minorDiagonal[row+col] = false;
				mainDiagonal[nQueen-1+row-col] = false;
			}
		}
	}
	bool canLay(int row, int col) {
		return !inColumn[col] && !minorDiagonal[row + col] && !mainDiagonal[nQueen - 1 + row - col];
	}
	void print() {
		for (int i = 0; i < solution.size(); i++) {
			cout << "solution " << i << " : " << endl;
			for (int row = 0; row < nQueen; row++) {
				for (int col = 0; col < solution[i][row]; col++) {
					cout << "O ";
				}
				cout << "X ";
				for (int col = solution[i][row]+1; col < nQueen; col++) {
					cout << "O ";
				}
				cout << endl;
			}
			cout << endl << endl;
		}
	}
private:
	int nQueen;
	vector<bool> inColumn;
	vector<bool> mainDiagonal;
	vector<bool> minorDiagonal;
	vector<vector<int> > solution;
};

int main()
{
	EightQueen queen(8);
	queen.process();
	queen.print();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值