八皇后问题

八皇后问题,回溯剪枝。

代码如下,仅供参考。

/*******************************************************************
* 程序说明:八皇后问题
*			在一个8*8的棋盘上放置8个皇后,不允许出现两个皇后在同一行、
*			同一列、主对角线和从对角线上。
* 分	析:(1)不在同一行和同一列上,这个比较好判断;
*			(2)不在同一条主对角线(或从对角线上)这个可分析如下:
*				对于任意一个点 dot[i][j](0<=i,j<=7),与该点在同一主
*				对角线上的点,其 i-j+7 的值相等,并且范围在[0,14];
*				与该点在同一从对角线上的点,其 i+j 的值相等,范围在
*				[0,14]。即是说:若两个点a[ik][jk]和b[if][jf]在同一
*				主对角线上,则 ik-jk+7 == if-jf+7 (之所以要 + 7,是
*				因为 i-j 可能 < 0,这是为了后续在代码中用数组作记录
*				方便);若两个点a[ik][jk]和b[if][jf]在同一从对角线上,
*				则 ik+jk == if+jf。故判断在坐标 (i,j) 的位置放上皇后
*				后,是否存在主对角线和从对角线上有其它的皇后,只需要
*				查询对应的记录数组就可以。
*			(3)在8*8的矩阵中,主对角线共有2*8-1=15条,反对角线(从对角线)
*				共有2*8-1=15条;
*			(4)时间复杂度为:O(n^2)
* 其	它:该8皇后问题也可以改为4皇后问题,只需要把对应的条件修改即
*			可。
*******************************************************************/

#define LOCAL
#include<iostream>
#include<cstdio>

using namespace std;

int chessBoard[8][8];//棋盘,0代表此位置无皇后,1代表此位置有皇后
int columnStates[8];//列状态,0代表此列没有皇后,1代表此列有皇后
int mainDiagStates[15];//主对角线状态,0代表该条主对角线上无皇后,1代表该条主对角线上有皇后
int countDiagStates[15];//从对角线(反对角线)状态,0,1代表的意义,同上。

int planCount;//共有多少种放置方案

void eightQueens(int i) {//尝试在第i行上放上一个皇后
	if (8 == i) {//由于行号的范围为:[0,7],所以当得到行参数坐标i==8时,
		++planCount;
		cout << "第 " << planCount << " 种放置方案:" << endl;
		for (int k = 0; k < 8; k++) {//表明前[0,7]行上已经成功放上皇后了,
			for (int w = 0; w < 8; w++) //故直接输出结果。
				cout << chessBoard[k][w] << " ";
			cout << endl;
		}
		cout << "------------------------" << endl;
		return;
	}
	for (int j = 0; j < 8; j++) {//尝试在第i行的第j列的位置上放置一个皇后
		if (columnStates[j]==0&&mainDiagStates[i-j+7]==0&&countDiagStates[i+j]==0){//检查是否满足3个条件
			//在该坐标(i,j)上安放一个皇后,并修改对应的标记数组
			chessBoard[i][j] = 1;
			columnStates[j] = 1;
			mainDiagStates[i - j + 7] = 1;
			countDiagStates[i + j] = 1;
			//尝试在下一行(i+1)放置一个皇后,递归调用
			eightQueens(i + 1);
			//重置
			chessBoard[i][j] = 0;
			columnStates[j] = 0;
			mainDiagStates[i - j + 7] = 0;
			countDiagStates[i + j] = 0;
		}
	}
}

int main() {
	memset(chessBoard, 0, sizeof(int) * 8 * 8);
	memset(columnStates, 0, sizeof(int) * 8);
	memset(mainDiagStates, 0, sizeof(int) * 15);
	memset(countDiagStates, 0, sizeof(int) * 15);
	planCount = 0;

	eightQueens(0);
	
	cout << "程序完成,共 " << planCount<<" 种方案!" << endl;
	_sleep(20000);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值