心得:这个八皇后问题一直困惑了很久,看到这篇文章对我帮助很大,一定要理解的是判断两个皇后是否冲突的条件,也就是要放置的皇后行与前一行皇后差的绝对值与列与前一个皇后列差的绝对值是否相等,这个一定要想明白。之后就是递归的实现,作者代码说的很详细,就不追叙了。
#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
/*
从棋盘的第一列开始,尝试在当前列的每一行摆放皇后。
如果当前在行列上摆放暂时不会引起冲突,则保存摆放的位置。
然后进入下一行重复上述操作,直到每一列都完成操作。
*/
int plan_num = 0; // 方案数量
int row_of_colm[11]; // 0元素弃置,第i个元素表示第i列上的皇后所在行的序号
bool if_occupied[11] = {false}; // 0元素弃置,第1到10个元素分别表示第1到10行时候已经放了皇后
int plan[92]; // 数组的每个元素表示一种方案
void NQueneP(int colm, int n) { // colmumn表示列号
if(colm == n + 1) { // 递归边界
plan_num++;
for(int i = 1; i <= n; i++) { // 摆放方案保存为一个整数
plan[plan_num] += row_of_colm[i] * pow(10, i - 1);
}
return; //返回上一层递归出口
}
//从第一行开始枚举试图摆放皇后
for(int row = 1; row <= n; row++) {
if(if_occupied[row] == false) { //当前行未被占用
bool flag = true; //试图在colm列row行摆放皇后
for(int pre = 1; pre < colm; pre++) { // 此时第1列到第colm-1列已处理完,这些列上的皇后已摆好,第i列上的皇后所在行号保存在row_of_colm[i]中,遍历前面的列检查是否会与当前行列上的皇后有对角冲突
if(abs(colm - pre) == abs(row - row_of_colm[pre])) { // 如果前面某皇后的行列与当前行列的差的绝对值相当,则对角冲突
flag = false; //不能在当前行列摆放
break;
}
}
//若为false,则不能在当前行列摆放,基于进入本次递归前确定的摆放位置加上本次探查的位置组成的摆放方案已经不可能成功,无需进一步摆放下去,直接进入下一行
if(flag == true) {
row_of_colm[colm] = row; //在colm列row行摆放皇后
if_occupied[row] = true; //标记row行已被占用
NQueneP(colm+1, n); //进行下一列处理
// 到达此处表明基于该行列的情况已经探查完,循环准备进入下一行
if_occupied[row] = false; // 清除占用标记
}
}
}
}
int main(){
int n = 8; // 皇后数
NQueneP(1, n); //从第一列开始摆皇后
sort(plan + 1, plan + (plan_num + 1));
int test_num;
while(scanf("%d", &test_num) != EOF) {
for(int i = 1; i <= test_num; i++) {
int index;
scanf("%d", &index);
printf("%d\n", plan[index]);
}
}
/*
cout << "共有" << plan_num << "种摆法" << endl;
for(int i = 0; i <= 92; i++) {
printf("%d %d\n", i, plan[i]);
}
*/
return 0;
}
转载自:https://blog.csdn.net/Zen_Ivan/article/details/107144016?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_aa&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_aa&utm_relevant_index=2