八皇后问题,回溯剪枝。
代码如下,仅供参考。
/*******************************************************************
* 程序说明:八皇后问题
* 在一个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;
}