思路
此题与n皇后问题十分类似,也是利用递归回溯求解。这题放2n个皇后,我采取的做法是,先放n个黑皇后,再放n个白皇后,具体实现见代码,一些细节方面我都标注出来了,并且做了详细解释。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=10;
int mp[N][N];
bool vy[N],vd[2*N],uvd[2*N];//这里用来给黑皇后做标记,列,正对角线,反对角线
bool vis[N][N];//这里给放过黑皇后的地方做标记,放过了黑皇后以后,白皇后就不能放在这个位置了
bool vy1[N],vd1[2*N],uvd1[2*N];//这里用来给黑皇后做标记,列,正对角线,反对角线
int n;
int ans;//答案
void dfs_w(int a);
//放入黑皇后函数
void dfs_b(int x){
if(x==n){//黑皇后放完了,那么开始从第一行放白皇后
dfs_w(0);
return ;
}
for(int i=0;i<n;i++){
if(mp[x][i]!=0 && !vy[i] && !vd[x+i] && !uvd[i-x+n]){//判断当前位置不能为0,当前列,对角线,反对角线没有被放过
vis[x][i]=true;//给当前位置放入黑皇后
vy[i]=vd[x+i]=uvd[i-x+n]=1;//标记
dfs_b(x+1);
vy[i]=vd[x+i]=uvd[i-x+n]=0;//移除标记
vis[x][i]=false;//移除黑皇后
}
}
}
//放入白皇后函数
void dfs_w(int a){
if(a==n){//白皇后到最后一行的下一行时,答案++;
ans++;
return ;
}
for(int i=0;i<n;i++){
if(mp[a][i]!=0 && !vy1[i] && !vd1[a+i] && !uvd1[i-a+n] && !vis[a][i]){
vis[a][i]=true;
vy1[i]=vd1[a+i]=uvd1[i-a+n]=1;
dfs_w(a+1);
vy1[i]=vd1[a+i]=uvd1[i-a+n]=0;
vis[a][i]=false;
}
}
}
int main(){
cin>>n;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin>>mp[i][j];
}
}
dfs_b(0);
cout<<ans<<endl;
return 0;
}