#include<iostream>
using namespace std;
const int N=30;
int n,ans;
int pos[N];//p[i]用来标记棋子放在第i行 其值表示放在哪一列
//保证棋子满足没有跟它同行 同对角线的棋子
int c[N];//c[j]表示棋子放在第j列 1表示它已经占领了位置 0表示没有
int p[N];//p[i+j]表示撇对角线 1表示其他棋子不能放棋 0表示可以放 易错点
int q[N];//q[i-j+n]表示捺对角线 1表示其他棋子不能放棋 0表示可以放
void print(){
if(ans<=3){//只输出前3种放案 按字典序
for(int i=1;i<=n;i++){
printf("%d ",pos[i]);//输出棋子所在列
}
printf("\n");
}
}
void dfs(int i){
if(i>n){//枚举所有的行之后 开始判定输出解决方案
ans++;print();return;
}
//从第1列开始枚举
for(int j=1;j<=n;j++){
//出现互斥关系 就不能放棋子
if(c[j]||p[i+j]||q[i-j+n])continue;
pos[i]=j;//占领位置
c[j]=p[i+j]=q[i-j+n]=1;//锁定同行、同列以及对角线
dfs(i+1);//枚举下一行
c[j]=p[i+j]=q[i-j+n]=0;//恢复现场
}
}
int main(){
cin>>n;
dfs(1);//从第1行第1列枚举
printf("%d",ans);//输出总方案数
return 0;
}
小知识点:
1)按行搜索空间
2)对角线与行列的映射关系 p[i+j] q[i-j+n]
3)N之所以开到30,是因为 p的范围为 【2,2*n】 q的范围为【1,2*n-1】 n最大取13,防止越界,因而开到30.